Java 如何在打开或关闭自动提交的情况下注入数据源,无论方法是否在事务中运行

Java 如何在打开或关闭自动提交的情况下注入数据源,无论方法是否在事务中运行,java,guice,jooq,apache-commons-dbcp,Java,Guice,Jooq,Apache Commons Dbcp,我有: JOOQ中的一个DAO类,在其构造函数中采用由Guice注入的javax.sql.DataSource 从DAO类调用方法的服务类 我想: 能够将服务类中的一些方法注释为需要事务的方法 可能的解决方案:身份证: 当使用Transactional注释对方法进行注释时调用的方法拦截器 如果出现异常,方法拦截器将调用rollback(),如果一切正常,方法拦截器将调用commit() Guice提供了一个javax.sql.DataSource(BoneCP池连接) BoneCP池连

我有:

  • JOOQ中的一个DAO类,在其构造函数中采用由Guice注入的
    javax.sql.DataSource
  • 从DAO类调用方法的服务类
我想:

  • 能够将服务类中的一些方法注释为需要事务的方法
可能的解决方案:身份证:

  • 当使用
    Transactional
    注释对方法进行注释时调用的方法拦截器
  • 如果出现异常,方法拦截器将调用
    rollback()
    ,如果一切正常,方法拦截器将调用
    commit()
  • Guice提供了一个
    javax.sql.DataSource
    (BoneCP池连接)
  • BoneCP池连接的
    defaultAutoCommit
    属性设置为
    false
最后,我的问题是:

  • 我希望将
    autocommit
    设置为
    false
    的数据源注入到从带有
    @Transactional
    注释的方法调用的所有方法中,在所有其他情况下,
    autocommit
    设置为
    true

如何实现这一点?

有一种简单但不优雅的方法:创建两个数据源实例并适当地注入

对于单个数据源实例,还有一种更复杂的方法。大致:

  • AutoCommit是java.sql.Connection的一个属性,它有一个setter
  • 实现org.jooq.ConnectionProvider以使jooq使用您的数据源实例
  • 此ConnectionProvider实现将有一个特殊的方法,例如startTransaction(),它可以创建autocommit=false的连接,并将其缓存在ThreadLocal成员中。即

    Connection conn = dataSource.createConnection();
    conn.setAutoCommit(false);
    threadLocal.set(conn);
    return conn;
    
  • ConnectionProvider.acquire()将执行类似smth的操作(简化版本):

  • 其他两个“特殊”方法是commit()和rollback()——它们将对缓存的连接执行相应的操作,关闭连接并将其从threadLocal中删除

  • @Transactional method拦截器将调用“特殊”方法

  • 本质上,这是最简单的事务管理器

    return threadLocal.get() != null ? 
           threadLocal.get() : 
           dataSource.createConnection();
    
    try {
      connectionProvider.startTransaction();
      interceptedMethod.invoke();
      connectionProvider.commit();
    } catch (Exception e) {
      connectionProvider.rollback();
    }