Giải pháp 1: Subclass
Đơn giản chỉ cần tạo một cài đặt tùy chỉnh của một PreparedStatement mà các đại biểu tất cả các cuộc gọi đến các tuyên bố chuẩn bị ban đầu, chỉ có thêm callbacks trong setObject, vv phương pháp. Ví dụ:
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);
}
};
}
Nếu bạn muốn lưu các thông số và nhận được chúng sau này, có rất nhiều giải pháp, nhưng tôi thích cách tạo ra một lớp mới như ParameterAwarePreparedStatement trong đó có các thông số trong bản đồ. Cấu trúc có thể là tương tự như sau:
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);
}
}
Giải pháp 2: Năng động, Proxy
giải pháp thứ hai này là ngắn hơn, nhưng dường như hacky hơn.
Bạn có thể tạo proxy động bằng cách gọi phương thức gốc trên java.lang.reflect.Proxy và ủy quyền tất cả các cuộc gọi trên phiên bản gốc. Ví dụ:
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;
}
Sau đó, bạn đánh chặn các setObject vv cuộc gọi bằng cách nhìn vào tên phương pháp và tìm cách để các đối số phương pháp thứ hai cho các giá trị của bạn.