简体   繁体   中英

Why my spring @Transactional with REQUIRED can't rollback?

I try to write a very simple code to test @Transactional, but it won't rollback when I use Propagation.REQUIRED. Here is the code.

    @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();
    }
}

When I test add() method alone by creating a new RuntimeException(), it will rollback. This is what I expected. However, when I run the test() method, the add() method won't rollback when delete() throws a new RuntimeException. It means the add() and delete() are not in a same transaction, but what I want is all the things to be rollback. Please help.

@Transactional on testPro() has no effect for 3 separate reasons:

  1. testPro() is static.
  2. Call is internal from test() in same class.
  3. Instance of class cases not created by Spring.

That means that add() and delete() are running in two separate transactions.

To prove it, try changing the propagation on delete() to MANDATORY . It will now throw exception saying that transaction is not in progress (or something to that effect) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM