【问题标题】:Why my spring @Transactional with REQUIRED can't rollback?为什么我的带有 REQUIRED 的 spring @Transactional 不能回滚?
【发布时间】:2016-12-31 19:19:32
【问题描述】:

我尝试编写一个非常简单的代码来测试@Transactional,但是当我使用Propagation.REQUIRED 时它不会回滚。这是代码。

    @Component
    public class A {

        private JdbcTemplate jdbcTemplate;

        @Resource(name="dataSource")
        public void setDataSource(DataSource dataSource) {
            this.jdbcTemplate = new JdbcTemplate(dataSource);
        }

        @Transactional(propagation=Propagation.REQUIRED)
        public void add(Person person) throws Exception {
        try {
            String sql = "insert into person (id, name) values(?,?)";
            jdbcTemplate.update(sql, new  Object[{person.getId(),person.getName()});
        } catch (Exception e) {
            throw new RuntimeException();
        }

        @Transactional(propagation=Propagation.REQUIRED)
        public void delete(String id) throws Exception {
            throw new RuntimeException();
            ***throw a RuntimeException on purpose***
        }
    }

    public class cases {

        @Transactional
        public static void testPro() throws Exception {
        try {
            AbstractApplicationContext aac = new ClassPathXmlApplicationContext("beans.xml");
            A a = (A) aac.getBean("a");
            a.add(***a random person***);
            a.delete("99");
        } catch (Exception e) {
            throw new RuntimeException();
        }
    }

    @Test
    public void test() throws Exception {
        testPro();
    }
}

当我通过创建一个新的 RuntimeException() 单独测试 add() 方法时,它会回滚。这是我所期望的。但是,当我运行 test() 方法时,当 delete() 抛出新的 RuntimeException 时,add() 方法不会回滚。这意味着 add() 和 delete() 不在同一个事务中,但我想要的是所有要回滚的东西。请帮忙。

【问题讨论】:

    标签: java spring transactional


    【解决方案1】:

    testPro() 上的@Transactional 无效,原因有 3 个:

    1. testPro() 是静态的。
    2. 来自同一类的 test() 的内部调用。
    3. cases 的实例不是由 Spring 创建的。

    这意味着add()delete() 在两个单独的事务中运行。

    为了证明这一点,请尝试将 delete() 上的传播更改为 MANDATORY。它现在会抛出异常,说事务不在进行中(或类似的东西)

    【讨论】:

    • new jdbcemplate(dataSource) 怎么样?我自己从未使用过它,但这对我来说似乎很奇怪。
    • @Walfrat 这就是你在使用 Spring JDBC 时应该做的事情。完全正常。
    • 你是对的。现在我知道这两种方法不在同一个事务中,但我不知道如何将它们放入同一个事务中。所以我删除了静态并尝试在案例上添加@Component并创建另一个调用testPro()的cals,但它仍然不起作用。
    • 您是否阅读了 Spring 文档的 Testing 章节?
    猜你喜欢
    • 1970-01-01
    • 2017-04-14
    • 2016-12-11
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 2019-06-30
    • 2016-12-19
    • 1970-01-01
    相关资源
    最近更新 更多