Spring@Transactional&x27;无法使用调用处理程序
我有一个JDBCSpring@Transactional&x27;无法使用调用处理程序,spring,transactions,dynamic-proxy,Spring,Transactions,Dynamic Proxy,我有一个JDBC连接的代理链,PreparedStatement和语句 ConnectionProxy: public class HikariConnectionProxy implements InvocationHandler { private final HikariDataSource dataSource; private final Connection delegate; private boolean committed; public st
连接的代理链
,PreparedStatement
和语句
ConnectionProxy:
public class HikariConnectionProxy implements InvocationHandler {
private final HikariDataSource dataSource;
private final Connection delegate;
private boolean committed;
public static Connection newInstance(HikariDataSource dataSource) throws SQLException {
final Connection connection = dataSource.getConnection();
return (Connection) Proxy.newProxyInstance(
connection.getClass().getClassLoader(),
connection.getClass().getInterfaces(),
new HikariConnectionProxy(dataSource, connection)
);
}
public static Connection newInstance(HikariDataSource dataSource, String username, String password) throws SQLException {
final Connection connection = dataSource.getConnection(username, password);
return (Connection) Proxy.newProxyInstance(
connection.getClass().getClassLoader(),
connection.getClass().getInterfaces(),
new HikariConnectionProxy(dataSource, connection)
);
}
private HikariConnectionProxy(HikariDataSource dataSource, Connection connection) throws SQLException {
this.dataSource = dataSource;
delegate = connection;
checkAutoCommit();
}
private void checkAutoCommit() throws SQLException {
if (!delegate.getAutoCommit()) {
delegate.setAutoCommit(true);
}
}
private void commit() throws SQLException {
delegate.commit();
committed = true;
}
private void close() throws SQLException {
// some code here
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Void.TYPE == method.getReturnType()) {
final String methodName = method.getName().toLowerCase();
if ("close".equals(methodName)) {
this.close();
return null;
} else if ("commit".equals(methodName)) {
this.commit();
return null;
}
} else if (PreparedStatement.class == method.getReturnType()) {
return ServiceBusPreparedStatementProxy.newInstance((PreparedStatement) method.invoke(delegate, args));
} else if (Statement.class == method.getReturnType()) {
return ServiceBusStatementProxy.newInstance((Statement) method.invoke(delegate, args));
}
return method.invoke(delegate, args);
}
}
语句代理:
public class ServiceBusStatementProxy implements InvocationHandler {
final boolean toCheckUnsigned;
final Statement delegate;
public static Statement newInstance(Statement statement) throws SQLException {
return (Statement) Proxy.newProxyInstance(
statement.getClass().getClassLoader(),
statement.getClass().getInterfaces(),
new ServiceBusStatementProxy(statement, statement.getConnection().getMetaData().getDatabaseProductName())
);
}
ServiceBusStatementProxy(Statement statement, String dbName) {
String dbNameLowerCase = dbName.toLowerCase();
toCheckUnsigned = dbNameLowerCase.contains("oracle") || dbNameLowerCase.contains("mysql") || dbNameLowerCase.contains("mariadb");
delegate = statement;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return toCheckUnsigned && ResultSet.class == method.getReturnType()
? ServiceBusResultSetProxy.newInstance((ResultSet) method.invoke(delegate, args))
: method.invoke(delegate, args);
}
}
public class ServiceBusPreparedStatementProxy extends ServiceBusStatementProxy implements InvocationHandler {
private static final Predicate<Runnable> isValidArithmetic = runnable -> {
try {
runnable.run();
return true;
} catch (ArithmeticException e) {
return false;
}
};
public static PreparedStatement newInstance(PreparedStatement preparedStatement) throws SQLException {
return (PreparedStatement) Proxy.newProxyInstance(
preparedStatement.getClass().getClassLoader(),
preparedStatement.getClass().getInterfaces(),
new ServiceBusPreparedStatementProxy(preparedStatement, preparedStatement.getConnection().getMetaData().getDatabaseProductName())
);
}
private ServiceBusPreparedStatementProxy(Statement statement, String dbName) {
super(statement, dbName);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (toCheckUnsigned && Void.TYPE == method.getReturnType()
&& args != null && args.length >= 3 && "setObject".equalsIgnoreCase(method.getName()) && args[1] != null) {
Class<?> valueClass = args[1].getClass();
if (BigInteger.class == valueClass) {
BigInteger bigInt = (BigInteger) args[1];
if (!isValidArithmetic.test(bigInt::longValueExact)) {
((PreparedStatement) delegate).setString((Integer) args[0], bigInt.toString());
return null;
}
}
}
return super.invoke(proxy, method, args);
}
}
PreparedStatementProxy:
public class ServiceBusStatementProxy implements InvocationHandler {
final boolean toCheckUnsigned;
final Statement delegate;
public static Statement newInstance(Statement statement) throws SQLException {
return (Statement) Proxy.newProxyInstance(
statement.getClass().getClassLoader(),
statement.getClass().getInterfaces(),
new ServiceBusStatementProxy(statement, statement.getConnection().getMetaData().getDatabaseProductName())
);
}
ServiceBusStatementProxy(Statement statement, String dbName) {
String dbNameLowerCase = dbName.toLowerCase();
toCheckUnsigned = dbNameLowerCase.contains("oracle") || dbNameLowerCase.contains("mysql") || dbNameLowerCase.contains("mariadb");
delegate = statement;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return toCheckUnsigned && ResultSet.class == method.getReturnType()
? ServiceBusResultSetProxy.newInstance((ResultSet) method.invoke(delegate, args))
: method.invoke(delegate, args);
}
}
public class ServiceBusPreparedStatementProxy extends ServiceBusStatementProxy implements InvocationHandler {
private static final Predicate<Runnable> isValidArithmetic = runnable -> {
try {
runnable.run();
return true;
} catch (ArithmeticException e) {
return false;
}
};
public static PreparedStatement newInstance(PreparedStatement preparedStatement) throws SQLException {
return (PreparedStatement) Proxy.newProxyInstance(
preparedStatement.getClass().getClassLoader(),
preparedStatement.getClass().getInterfaces(),
new ServiceBusPreparedStatementProxy(preparedStatement, preparedStatement.getConnection().getMetaData().getDatabaseProductName())
);
}
private ServiceBusPreparedStatementProxy(Statement statement, String dbName) {
super(statement, dbName);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (toCheckUnsigned && Void.TYPE == method.getReturnType()
&& args != null && args.length >= 3 && "setObject".equalsIgnoreCase(method.getName()) && args[1] != null) {
Class<?> valueClass = args[1].getClass();
if (BigInteger.class == valueClass) {
BigInteger bigInt = (BigInteger) args[1];
if (!isValidArithmetic.test(bigInt::longValueExact)) {
((PreparedStatement) delegate).setString((Integer) args[0], bigInt.toString());
return null;
}
}
}
return super.invoke(proxy, method, args);
}
}
您正在处理自动提交。。。不要。@M.Deinum我只是在从池借用连接时检查自动提交。当我仍然使用代理连接但不使用代理语句时,一切都正常。不,您不需要。您将其显式设置为
true
这不是一个检查,而是一个集合。使用Transactions时,不应将其设置为true
。另外,你能详细说明什么不起作用吗?如果出现异常,请添加stacktrace。@M.Deinum删除了此代码,但这一点都没有帮助…至少它会清理代码并保持自动提交不变。问题的第二部分呢,什么不起作用?另外,如何使用这些调用处理程序为Hikari创建代理?