【问题标题】:Understanding Spring Transaction boundaries了解 Spring 事务边界
【发布时间】:2011-04-04 12:12:40
【问题描述】:

我正在努力消除我的疑虑。 Spring 事务边界与以下示例。

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void test() {    
    test1();
    test2();        
}

@Transactional(propagation=Propagation.NOT_SUPPORTED, readOnly=false)
public void test1() {
    this.jdbcTemplate.execute("INSERT INTO TEST VALUES('T', 'C2', 0, 1)");      
}

@Transactional(propagation=Propagation.SUPPORTS, isolation=Isolation.READ_UNCOMMITTED, readOnly=true)
public void test2() {
    System.out.println(this.jdbcTemplate.queryForInt("select count(*) from TEST"));         
}

我想将 test2() 方法与 test1() 隔离,即每次调用 test() 时 test2() 不应读取 test1() 提交的数据。 请建议是否可以使用传播或隔离属性来处理这种情况。

提前致谢。

【问题讨论】:

    标签: java spring


    【解决方案1】:

    事务属性应用于外部调用,而不是由 bean 方法(例如您的案例)进行的内部调用。如果您希望将事务边界应用于您的调用,您应该注入您的 bean 实例,如下所示。但我认为这不是好的做法,我不会推荐.. 完成的正确方法是定义另一个 spring bean 并将其与您以前的 bean 相关联,并将您的测试方法放在这个新 bean 上。

    @Service("yourBean")
    @Transactional
    public class YourBeanClass implement IYourBean {
    
       @Resource(name="yourBean")
        IYourBean yourBean;
    
            @Transactional(propagation=Propagation.REQUIRED)
        public void test() {    
            yourBean.test1();
            yourBean.test2();       
        }
    
        @Transactional(propagation=Propagation.REQUIRED)
        public void test1() {
            this.jdbcTemplate.execute("INSERT INTO TEST VALUES('T', 'C2', 0, 1)");      
        }
    
        @Transactional(propagation=Propagation.NOT_SUPPORTED)
        public void test2() {
            System.out.println(this.jdbcTemplate.queryForInt("select count(*) from TEST"));         
        }
    

    }

    解决此特定问题的替代和更好的方法;

     @Service("otherBean")
        @Transactional
        public class OtherBeanClass implement IOtherBean {
    
         @Autowired
         IYourBean yourBean;
    
          @Transactional(propagation=Propagation.REQUIRED)
            public void test() {    
                yourBean.test1();
                yourBean.test2();       
            }
    
       }
    
    
    
        @Service("yourBean")
        @Transactional
        public class YourBeanClass implement IYourBean {
    
    
    
            @Transactional(propagation=Propagation.REQUIRED)
            public void test1() {
                this.jdbcTemplate.execute("INSERT INTO TEST VALUES('T', 'C2', 0, 1)");      
            }
    
            @Transactional(propagation=Propagation.NOT_SUPPORTED)
            public void test2() {
                System.out.println(this.jdbcTemplate.queryForInt("select count(*) from TEST"));         
            }
    }
    

    【讨论】:

    • 哦,对了,我一开始不明白是什么让代码看起来很奇怪。实际上,对于来自 test() 的 test1 和 test2 调用,Transactional 可能会被忽略。
    • 我指的是问题中的原始代码。另外我不确定 NOT_SUPPORTED 是 test2 的安全选择。在某些情况下它不会导致现有事务的提交吗?我提出了 REQUIRES_NEW ,它看起来像一个更安全的选择,因为它只会获取另一个数据库连接。
    • 不,不会导致当前事务提交,当前事务在not_supported bean方法执行过程中被暂停,当它执行完成后,恢复原来的事务..
    【解决方案2】:

    test() 应该是 SUPPORTS,所以如果有一个现有的 TX,它将被传播到 test1()。 test1() 应该是必需的,以便您的插入实际提交。 test2() 应该是 REQUIRES_NEW。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-22
      • 2016-06-05
      • 2019-04-13
      • 2015-01-01
      • 2019-07-05
      • 2020-07-07
      • 2015-08-18
      • 1970-01-01
      相关资源
      最近更新 更多