2

ストアド プロシージャ (Oracle) を呼び出したいと思います。私のプロシージャー呼び出しは動的であるため、プロシージャーのパラメーターを動的に管理する必要があります。instanceof問題は、プライマリ型ではうまく機能しないため、キーワードの使用を避けたいことです。そのようなプロシージャを呼び出すよりクリーンな方法はありますか?

    public void executeProcedure(StoredProcedure proc) {        
        LinkedList<ProcedureParameter<?>> parameters = proc.getParameters();

        CallableStatement statement = connection.prepareCall("{ call MY_PACKAGE.MY_PROCEDURE( ?, ?, ? ) }");

        for (int i = 0; i < parameters.size(); i++) {
            Object paramValue = parameters.get(i).getValue();

            // Beginning of smelly code

            if (paramValue instanceof String) {
                statement.setString(i + 1, (String) paramValue);
            }
            else if (paramValue instanceof ...) {
                ...
            }
            else {
                ...
            }

            // End of smelly code
        }

        statement.execute();            
    }

 

    public class ProcedureParameter<E> {
        private String name;
        private E value;

        public ProcedureParameter(String name) {
            this.name = name;
        }

        public ProcedureParameter(String name, E value) {
            this.name = name;
            this.value = value;
        }

        // Getters and setters
    }

ご意見ありがとうございます。

4

3 に答える 3

1

私は別の解決策を実装します。それはおそらく最良の解決策ではありませんが、私の意見では、臭いはありません。

インターフェイスと同様StoredProcedureに、各ストアドプロシージャはこのインターフェイスを実装します。call ...したがって、開発者は実装するプロシージャに必要なパラメータのタイプを知っているため、各実装にはステートメントを返すメソッドが含まれます。

于 2012-06-21T15:24:25.450 に答える
1

instanceof なしで必要な機能を実装するのに役立つと思います: http://en.wikipedia.org/wiki/Visitor_pattern

于 2012-06-21T14:20:56.010 に答える
1

リフレクションを使用することもできますが、これは低速であり、コンパイラがメソッド呼び出しが正しいことを確認するためのチェックを妨げるため、お勧めできません。各クラスを対応するCallableStatementメソッドにマップします。たとえばString、「setString」にマップされます。

List<ProcedureParameter<?>> parameters = proc.getParameters();
CallableStatement statement = connection.prepareCall("{ call MY_PACKAGE.MY_PROCEDURE( ?, ?, ? ) }");

Map<Class<?>, String> methods = new HashMap<Class<?>, String>();
methods.put(String.class, "setString");
//...

for (int i = 0; i < parameters.size(); i++) {
  Object paramValue = parameters.get(i).getValue();
  Class<?> paramValueClass = paramValue.getClass();
  String stmtMethod = methods.get(paramValueClass);
  if (stmtMethod != null){
    Method method = statement.getClass().getMethod(stmtMethod, int.class, paramValueClass);
    method.invoke(statement, i+1, paramValue);
  } else {
    //error
  }
}
于 2012-06-21T14:46:30.323 に答える