【问题标题】:using spring's @Transactional on a method which also makes use of aop:after advice在也使用 aop:after 建议的方法上使用 spring 的 @Transactional
【发布时间】:2011-09-14 17:16:43
【问题描述】:

我想看看是否已经有类似的问题,但找不到,在这里。

我们有一个遗留代码,其中单个 BO 使用反射对许多 DAO 进行方法调用。 为了简单起见,我修改了代码。

@Transactional
class EndpointData1DAO implements DAO{
  void inserData() {
   // insert data 1
  }
}

@Transactional
class EndpointData2DAO implements DAO{
  void inserData() {
    // insert data 2
  }
}

class MachoBO {
 void handleEverything(String daoName) {
   DAO dao = getDAOUsingReflection(daoName);
   dao.insertData();
 }
}

问题是,需求发生了变化,所以当在 EndpointData1DAO 上调用 insertData() 时,也必须调用 EndpointData2DAO 的 insertData。

我可以简单地将 EndpointData2DAO 添加为 EndpointData1DAO 的成员,但这严重违反了 SRP 并使其变得丑陋。

所以我写了一个注释 @ExecuteAfter(clazz=EndpointData2DAO.class, method="insertData") 获取 EndpointData2DAO 的实例并调用 insertData(), 在它注解的类的方法被执行之后,通过使用aop:after,使得给定的

@Transactional
@ExecuteAfter(clazz=EndpointData2DAO.class, method="insertData") 
class EndpointData1DAO implements DAO{
  void inserData() {
   System.out.println("insert1");
  }
}

@Transactional
class EndpointData2DAO implements DAO{
  void inserData() {
   System.out.println("insert2");
  }
}

class MachoBO {
 void handleEverything(String daoName) {
   DAO dao = getDAOUsingReflection(daoName);
   dao.insertData();
 }

1 2 将在调用 machoBO.handleEverthing("Data1"); 时打印出来;

现在我的问题是, EndpointData1DAO 和 EndpointData2DAO 的 insertData() 会在同一个物理事务中吗? 也就是说,EndpointData2DAO 的 insertData() 中的运行时异常会回滚 EndpointData1DAO 的 insertData() 插入的数据吗?

多谢提前~!!

【问题讨论】:

    标签: java spring annotations aop transactional


    【解决方案1】:

    我通过实际运行测试找到了答案。

    通过执行以下代码,我能够找出当前正在运行的事务的名称。

    ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
            Class tsmClass = contextClassLoader.loadClass("org.springframework.transaction.support.TransactionSynchronizationManager");
            String transactionName = (String) tsmClass.getMethod("getCurrentTransactionName", null).invoke(null, null);
            System.out.println(transactionName);
    

    当我把 MachoBO 上的@Transactional 如下,

    @Transactional
    class MachoBO {
     void handleEverything(String daoName) {
       DAO dao = getDAOUsingReflection(daoName);
       dao.insertData();
     }
    

    由于@Transactional 有一个“方法范围”, 当machoBO.handleEverthing("Data1"); 被调用时, 两个 DAO 的 inserData() 都在事务名称“MachoBO.handleEverthing”下执行。

    但是,当 MachoBO 未使用 @Transactional 注释时, 两个 DAO 的 inserData() 不共享相同的方法范围,因此, 在单独的事务下执行,即“EndpointData1DAO.inserData”和“EndpointData2DAO.insertData”。

    应该注意(虽然很明显),当一个 DAO 使用 @Transactional 注释并且传播设置为 REQUIRES_NEW 时,DAO 的 insertData() 在单独的事务中运行。

    【讨论】:

      猜你喜欢
      • 2011-12-31
      • 2020-01-23
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      • 2013-05-17
      • 2018-07-26
      相关资源
      最近更新 更多