2016-12-31 36 views
1

我嘗試編寫一個非常簡單的代碼來測試@Transactional,但在使用Propagation.REQUIRED時它不會回滾。這是代碼。爲什麼我的Spring @Transactional與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()方法時,add()方法在delete()拋出新的RuntimeException時不會回滾。這意味着add()和delete()不在同一個事務中,但我想要的是所有事情都要回滾。請幫忙。

回答

6

@TransactionaltestPro()具有3個獨立的原因沒有效果:

  1. testPro()是靜態的。
  2. 從同一班的test()內部致電。
  3. 類別cases的實例不是由Spring創建的。

這意味着add()delete()正在兩個獨立的事務中運行。

要證明這一點,請嘗試將delete()上的傳播更改爲MANDATORY。它現在會拋出異常,說該交易沒有進行中(或者是這個效果)

+0

'new jdbcemplate(dataSource)'?我從來沒有用過它,但這對我來說似乎很奇怪。 – Walfrat

+0

@Walfrat這就是你在使用Spring JDBC時要做的事情。非常正常。 – Andreas

+0

你說得對。現在我知道這兩種方法不在同一個事務中,但我不知道如何將它們放入同一個事務中。所以我刪除了靜態,並試圖在案例中添加@Component,並創建了另一個調用testPro()的方法,但仍然無效。 –

相關問題