Java动态事务代理 - 连接初始化

时间:2012-07-11 07:50:58

标签: java reflection transactions

我有这样的事情:
1) DAO类,带有用于执行事务的方法,例如withdrawSum(int idAccount, float amount)putSum(int idAccount, float amount),它们使用java.sql.Connection和java.sql.PreparedStatement类来执行原子操作与DB。
2)java.lang.reflect。 InvocationHandler 实现者,whick用于在事务之前获取连接并在事务之后提交/回滚:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Connection connection = null;
    try{
        connection = DaoUtil.INSTANCE.getConnection();
        connection.setAutoCommit(false);
        method.invoke(connection, args);
        connection.commit();
    } catch(InvocationTargetException ex){
        connection.rollback();
    } finally{
        DaoUtil.INSTANCE.closeConnection(connection);
    }
    return null;
}

3)事务管理器,它创建代理实例并使用其执行事务的帮助调用方法,如下所示:

TransactionManager transManager = new TransactionManager();
InvocationHandler transHandler = new MyInvocationHandler(transManager);
TransactionManager proxy = (TransactionManager) Proxy.newProxyInstance(
            transManager.getClass().getClassLoader(), transManager.getClass().getInterfaces(), transHandler);
proxy.transferMoney(withdrawAccountid, putAccountId, transactionSum);

.....

   public void transferMoney(int withdrawAccountid, int putAccountId, float transactionSum){
            AccountDao.getInstance().withdrawSum(withdrawAccountid, transactionSum);
            AccountDao.getInstance().putSum(putAccountId, transactionSum);
    }

问题是:要在DAO方法中执行语句,我需要初始化连接对象。它是初始化的并传递给InvocationHandler的 invoke - 方法。如何在DAO方法中正确初始化?有任何想法吗?提前谢谢。

1 个答案:

答案 0 :(得分:1)

由于事务自然地与线程相关联,因此这里的典型方法是在事务范围内将Connection存储在ThreadLocal存储中。

然后,您可以使用不同的方法将这些连接提供给DAO:

  • DAO可以通过调用一些静态方法

  • 来获取Connection
  • 可以将自定义DataSource注入到DAO中 - 其getConnection()方法将返回与当前事务关联的连接,请注意应该代理连接以忽略close() 。此方法不会将DAO与事务管理代码耦合。

另请注意,所有这些内容都已由某些库实现,例如,Spring Framework。也许您可以利用它而不是创建自己的解决方案,或者至少看看他们的设计(在Spring中,分别通过DataSourceUtilsTransactionAwareDataSourceProxy实现了获取连接的不同方法。)

另见: