spring的事務傳播機制
@Service
public class ServiceA {
@Autowired
ServiceB serviceB;
public void methodA() {
serviceB.methodB();
}
}
@Service
public class ServiceB {
public void methodB() {
}
}
事務傳播機制 Propagation.REQUIRED(預設)
Propagation.REQUIRED(預設)
@Transactional(propagation = Propagation.REQUIRED)
# 如果有事務, 那麼加入事務, 沒有的話建立一個(預設情況下)
如果目前正在運作的事務不在其他事務中,則新啟一個事務
例如:方法B使用了
@Transactional(propagation = Propagation.REQUIRED)
1、那麼如果方法A已經啟用了事務,那麼B就不啟用事務。這時候方法A與方法B任意一方出現異常,都會復原。
2、那麼如果方法A未啟用了事務,那麼B就新啟一個事務。此時,A出現異常不影響B,B方法出現異常也不影響A
事務傳播機制 Propagation.REQUIRES_NEW
Propagation.REQUIRES_NEW
@Transactional(propagation = Propagation.REQUIRES_NEW)
# 建立事務,如果目前存在事務,則把目前事務挂起
# 這個方法會獨立送出事務,不受調用者影響,父級異常,他也是正常送出
這個方法會獨立送出事務,不受調用者影響,父級異常,他也是正常送出
也就是說事務B是一個獨立的事務,不受父類影響,但是如果事務B發生了異常,事務A會捕捉到異常,A就會發生復原。
事務傳播機制 Propagation.NESTED
Propagation.NESTED
@Transactional(propagation = Propagation.NESTED)
#
NESTED事務跟REQUIRED事務差別就在這裡,NESTED事務是復原到復原點,而復原點生成是在進入内嵌事務的時候,外面事務是不會復原的
@Service
public class ServiceA {
@Autowired
ServiceB serviceB;
@Autowired
SchoolMapper mapper;
@Transactional
public void methodA() {
try {
School school = new School();
school.setGrade("9");
school.setName("AAAAAAAAA");
school.setSex("n");
school.setTelephone("1111111111");
mapper.insert(school);
-- 復原點
serviceB.methodB();
} catch (Exception e) {
}
}
}
@Service
public class ServiceB {
@Autowired
SchoolMapper mapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
int i = 1 / 0;
}
}
上面方法B使用的Propagation.
REQUIRES_NEW
聲明事務,并且抛出了異常。而方法A調用B并處理了該異常,那麼NESTED事務是復原到復原點,復原點就是進入内嵌事務的地方。是以方法A儲存的school記錄會成功。
補充復原點概念:某轉賬業務有 A B C D 四個事務。 需求:AB(必須)復原點 CD(可選)。如果發生異常,如果有復原點則會復原CD,并送出AB,如果沒有復原點,則AB CD全部復原。
這裡有個想法,既然方法A可以捕捉異常,那麼
propagation = Propagation.REQUIRED
是否也可以呢?
于是将方法B的事務傳播改為
propagation = Propagation.REQUIRED
@Service
public class ServiceA {
@Autowired
ServiceB serviceB;
@Autowired
SchoolMapper mapper;
@Transactional
public void methodA() {
try {
School school = new School();
school.setGrade("9");
school.setName("AAAAAAAAA");
school.setSex("n");
school.setTelephone("1111111111");
mapper.insert(school);
serviceB.methodB();
// int i = 1 / 0;
} catch (Exception e) {
}
}
}
@Service
public class ServiceB {
@Autowired
SchoolMapper mapper;
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
School school = new School();
school.setGrade("1");
school.setName("BBBBBBBB");
school.setSex("n");
school.setTelephone("1111111111");
mapper.insert(school);
int i = 1 / 0;
}
}
此時發現會抛出異常
Transaction rolled back because it has been marked as rollback-only
發現selectA調用selectB,如果selectB抛出Exception,selectA中捕獲Exception但是并不繼續向外抛出,最後會出現錯誤。
糾其原理其實很簡單,在selectB傳回的時候,transaction被設定為rollback-only了,但是selectA正常消化掉,沒有繼續向外抛。
那麼selectA結束的時候,transaction會執commit操作,但是 transaction已經被設定為 rollback-only了。
那如果方法B不配置事務,然後方法B抛出異常,方法A捕獲異常,會怎麼辦呢
@Service
public class ServiceA {
@Autowired
ServiceB serviceB;
@Autowired
SchoolMapper mapper;
@Transactional
public void methodA() {
try {
School school = new School();
school.setGrade("9");
school.setName("AAAAAAAAA");
school.setSex("n");
school.setTelephone("1111111111");
mapper.insert(school);
serviceB.methodB();
// int i = 1 / 0;
} catch (Exception e) {
}
}
}
@Service
public class ServiceB {
@Autowired
SchoolMapper mapper;
// @Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
School school = new School();
school.setGrade("1");
school.setName("BBBBBBBB");
school.setSex("n");
school.setTelephone("1111111111");
mapper.insert(school);
int i = 1 / 0;
}
}
會發現A與B方法的資料庫操作都成功了。
事務傳播機制 Propagation.SUPPORTS
Propagation.SUPPORTS
@Transactional(propagation = Propagation.SUPPORTS)
# 如果目前存在事務,則加入事務,如果目前不存在事務,則以非事務運作,這個和不寫沒有差別。
事務傳播機制 Propagation.NOT_SUPPORTED
Propagation.NOT_SUPPORTED
@Transactional(propagation = Propagation.NOT_SUPPORTED)
# 以非事務運作,如果目前存在事務,則把目前事務挂起
事務傳播機制 Propagation.MANDATORY
(強制)
Propagation.MANDATORY
@Transactional(propagation = Propagation.MANDATORY)
# 如果目前存在事務,則運作再目前事務中;如果目前不存在事務,則抛出異常,即父級方法必須有事務
事務傳播機制 Propagation.NEVER
Propagation.NEVER
@Transactional(propagation = Propagation.NEVER)
# 以非事務運作,如果目前存在事務,則抛出異常,即父級方法必須沒有事務