SQLExceptionの汎用ロガーを作成していますが、PreparedStatementに渡されたパラメータを取得したいと思いますか?私はそれらの数を得ることができました。ボルダーからPreparedStatementからパラメータを取得するには?
ParameterMetaData metaData = query.getParameterMetaData();
parameterCount = metaData.getParameterCount();
SQLExceptionの汎用ロガーを作成していますが、PreparedStatementに渡されたパラメータを取得したいと思いますか?私はそれらの数を得ることができました。ボルダーからPreparedStatementからパラメータを取得するには?
ParameterMetaData metaData = query.getParameterMetaData();
parameterCount = metaData.getParameterCount();
短い回答:できません。
長い答え:すべてのJDBCドライバはパラメータ値をどこかに保持しますが、標準的な方法はありません。
デバッグまたは同様の目的のためにそれらを印刷したい場合、あなたはいくつかのオプションがあります:
はパススルーJDBCドライバ(基礎としてp6spyまたはlog4jdbcを使用)パラメータのコピーを保持して作成します。それらを読むための公開APIを提供しています。
Java Reflection API(Field.setAccessible(true)
はあなたの友人です)を使用して、JDBCドライバのプライベートデータ構造を読み込みます。それが私の好みのアプローチです。私は、パラメータをデコードすることができるDB固有の実装に委譲するファクトリを持っており、それによって、getObject(int column)
を介してパラメータを読み取ることができます。
バグレポートを提出して、例外が改善されることを尋ねます。特にオラクルは、何が間違っているかを教えてくれるときには、本当にひどいです。
This articleは、DB 2 "特定" ahtoulgh、ParameterMetadataの使用の完全な例を与えます。
は、単にその代表者、元のプリペアドステートメントにすべてのコールを、唯一のsetObjectにコールバックを追加する、などの方法のPreparedStatementのカスタム実装を作成します。例:
public PreparedStatement prepareStatement(String sql) {
final PreparedStatement delegate = conn.prepareStatement(sql);
return new PreparedStatement() {
// TODO: much more methods to delegate
@Override
public void setString(int parameterIndex, String x) throws SQLException {
// TODO: remember value of X
delegate.setString(parameterIndex, x);
}
};
}
あなたはパラメータを保存し、後でそれを取得したい場合は、そこに多くのソリューションがありますが、私はマップ内のパラメータを持っているParameterAwarePreparedStatementのように新しいクラスを作成することを好みます。構造は次のように考えられます。
public class ParameterAwarePreparedStatement implements PreparedStatement {
private final PreparedStatement delegate;
private final Map<Integer,Object> parameters;
public ParameterAwarePreparedStatement(PreparedStatement delegate) {
this.delegate = delegate;
this.parameters = new HashMap<>();
}
public Map<Integer,Object> getParameters() {
return Collections.unmodifiableMap(parameters);
}
// TODO: many methods to delegate
@Override
public void setString(int parameterIndex, String x) throws SQLException {
delegate.setString(parameterIndex, x);
parameters.put(parameterIndex, x);
}
}
この第二の溶液は短いですが、より多くのハックようです。
java.lang.reflect.Proxyでファクトリメソッドを呼び出し、すべての呼び出しを元のインスタンスに委任することで、ダイナミックプロキシを作成できます。例:
public PreparedStatement prepareStatement(String sql) {
final PreparedStatement ps = conn.prepareStatement(sql);
final PreparedStatement psProxy = (PreparedStatement) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class<?>[]{PreparedStatement.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("setLong")) {
// ... your code here ...
}
// this invokes the default call
return method.invoke(ps, args);
}
});
return psProxy;
}
は、その後、あなたはメソッド名を見て、自分の価値観のための第二の方法の引数を調べることで
などのsetObject、呼び出しをインターセプト。