事務的傳播性

1.REQUIRED(默認模式)

方法被調用時自動開啓事務,在事務範圍內使用則使用同一個事務,否則開啓新事務即業務方法需要在一個容器裏運行,如果方法運行時,已經處在一個事務中,那麼加入到這個事務,否則自己新建一個新的事務。

@Test
public void test{
      addStudent();
}
@Transactional(propagation = Propagation.REQUIRED)
public void addStudent(){
	  String sql = "insert into student(name) values("王華")";
      jdbcTemplate.execute(sql);
      addTeacher();
      throw new RuntimeException();   //拋異常
}

@Transactional(propagation = Propagation.REQUIRED)
public void addTeacher(){
       String sql = "insert into teacher(name) values ("李亮")";
       jdbcTemplate.execute(sql);
}

經測試:無論addStudent()還是addTeacher(),如果只要有一個拋出異常,則全都回滾;不拋異常,數據正常提交

2.REQUIRES_NEW

不管是否存在事務,該方法總會爲自己發起一個新的事務。如果方法已經運行在一個事務中,則原有事務掛起,新的事務被創建

@Test
public void test{
      addStudent();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addStudent(){
	  String sql = "insert into student(name) values("王華")";
      jdbcTemplate.execute(sql);
      addTeacher();
      throw new RuntimeException();   //拋異常
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addTeacher(){
       String sql = "insert into teacher(name) values ("李亮")";
       jdbcTemplate.execute(sql);
}

經測試:學生數據不能正確提交,教師信息被正確提交。說明這兩個操作是在兩個獨立的事務中運行,並且只要方法被調用就開啓事務。

3.Supports

自身不會開啓事務,在事務範圍內則使用相同事務,否則不使用事務,即該方法在某個事務範圍內被調用,則方法成爲該事務的一部分,如果方法沒有在事務中被調用,該方法就在沒有事務的環境下執行,因爲Supports默認自身不開啓事務

@Test
public void test{
      addStudent();
}
@Transactional(propagation = Propagation.SUPPORTS)
public void addStudent(){
	  String sql = "insert into student(name) values("王華")";
      jdbcTemplate.execute(sql);
      addTeacher();
      throw new RuntimeException();   //拋異常
}

@Transactional(propagation = Propagation.SUPPORTS)
public void addTeacher(){
       String sql = "insert into teacher(name) values ("李亮")";
       jdbcTemplate.execute(sql);
}

經測試:學生數據和教師數據都被正確提交。說明這兩個操作沒有被spring管理和開啓事務,而是使用了本地事務,由於本地事務默認自動提交因此數據都提交成功,但它們使用的卻不是同一個事務,一旦出現異常將導致數據的不一致

4.NOT_SUPPORTED

聲明方法不需要事務,即如果方法沒有關聯到一個事務,容器不會爲他開啓事務,如果方法在一個事務中被調用,該事務會被掛起,調用結束後,原先的事務會恢復執行

@Test
public void test{
      addStudent();
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void addStudent(){
	  String sql = "insert into student(name) values("王華")";
      jdbcTemplate.execute(sql);
      addTeacher();
      throw new RuntimeException();   //拋異常
}

@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void addTeacher(){
       String sql = "insert into teacher(name) values ("李亮")";
       jdbcTemplate.execute(sql);
}

經測試:學生和老師數據都正確提交。說明這兩個操作沒有被spring管理和開啓事務,而是使用了本地事務,由於本地事務默認自動提交因此數據都提交成功

@Test
public void test{
      addStudent();
}
@Transactional(propagation = Propagation.REQUIRED)
public void addStudent(){
	  String sql = "insert into student(name) values("王華")";
      jdbcTemplate.execute(sql);
      addTeacher();
      throw new RuntimeException();   //拋異常
}

@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void addTeacher(){
       String sql = "insert into teacher(name) values ("李亮")";
       jdbcTemplate.execute(sql);
}

經測試:學生數據提交失敗,教師數據提交成功。說明學生操作開啓了事務,老師操作沒有開啓事務,而是使用了本地事務

5.MANDATORY

該方法只能在一個已經存在的事務中執行,業務方法不能發起自己的事務。如果在沒有事務的環境下被調用,容器拋出例外

@Test
public void test{
      addStudent();
}
@Transactional(propagation = Propagation.REQUIRED)
public void addStudent(){
	  String sql = "insert into student(name) values("王華")";
      jdbcTemplate.execute(sql);
      addTeacher();
      throw new RuntimeException();   //拋異常
}

經測試:代碼報錯,org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation ‘mandatory’,沒有找到事務環境

6.NEVER

該方法絕對不能在事務範圍內執行。如果在就拋例外。只有該方法沒有關聯到任何事務,才正常執行

    @Test
    public void test{
          addStudent();
    }
    @Transactional(propagation = Propagation.REQUIRED)
    public void addStudent(){
    	  String sql = "insert into student(name) values("王華")";
          jdbcTemplate.execute(sql);
          addTeacher();
          throw new RuntimeException();   //拋異常
    }
    
    @Transactional(propagation = Propagation.NEVER)
    public void addTeacher(){
           String sql = "insert into teacher(name) values ("李亮")";
           jdbcTemplate.execute(sql);
    }

經測試:代碼報錯,由於學生開啓了事務,當調用老師方法時由於其傳播特性爲never,因此報存在事務錯誤:org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation ‘never’

7.NESTED

如果一個活動的事務存在,則運行在一個嵌套的事務中。如果沒有活動事務,則按REQUIRED屬性執行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的保存點。內部事務的回滾不會對外部事務造成影響。它只對DataSourceTransactionManager事務管理器起效(需要JDBC3.0以上支持)

@Test
public void test{
      addStudent();
}
@Transactional(propagation = Propagation.NESTED)
public void addStudent(){
	  String sql = "insert into student(name) values("王華")";
      jdbcTemplate.execute(sql);
      addTeacher();
      throw new RuntimeException();   //拋異常
}

@Transactional(propagation = Propagation.NESTED)
public void addTeacher(){
       String sql = "insert into teacher(name) values ("李亮")";
       jdbcTemplate.execute(sql);
}

經測試:代碼報錯,教師數據和學生數據都沒有提交成功。說明其按照REQUIRED特性運行。對於嵌套事務,大家可以模擬兩個數據源,一方的失敗不會影響另一方

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章