1. Spring支持編程式事務(wù)管理TransactionTemplate
和聲明式事務(wù)管理@Transactional
兩種方式
和編程式事務(wù)相比堆生,聲明式事務(wù)唯一不足地方是最細(xì)粒度只能作用到方法級別朴皆,無法做到像編程式事務(wù)那樣可以作用到代碼塊級別季蚂。但是即便有這樣的需求啊掏,也存在很多變通的方法,比如臼膏,可以將需要進(jìn)行事務(wù)管理的代碼塊獨(dú)立為方法等等(比如使用
AopContext.currentProxy()
)危尿。
2. @Transactional
可通過AopContext.currentProxy()
解決在同一個類中,非事務(wù)方法A調(diào)用事務(wù)方法B,事務(wù)失效
B方法被A調(diào)用错沽,對B方法的切入失效簿晓,但加上 AopContext.currentProxy() 創(chuàng)建了代理類,在代理類中調(diào)用該方法前后進(jìn)行切入千埃。對于B方法 proxy.B憔儿,執(zhí)行的過程是先記錄日志后調(diào)用方法體,但在A方法 proxyA中調(diào)用只能對A進(jìn)行增強(qiáng)放可,A里面調(diào)用B使用的是對象.B(),而不是 $proxy.B(),所以對B的切入無效谒臼。
注:AopContext.currentProxy()使用了ThreadLocal保存了代理對象,因此
AopContext.currentProxy().B()就能解決耀里。
public class Demo {
public void methodA () {
...
// 獲取當(dāng)前代理類蜈缤,保證同一個類中非事務(wù)方法調(diào)用事務(wù)方法時事務(wù)生效
((Demo) AopContext.currentProxy()).methodA();
...
}
@Transactional(rollbackFor = Exception.class)
public void methodB () {
...
}
}
- 使用
@Transactional
聲明式事務(wù)
是否在同一個類 | 調(diào)用 | 事務(wù)是否生效 |
---|---|---|
在不同類中 | 事務(wù)方法A調(diào)用非事務(wù)方法B | 事務(wù)生效 |
在不同類中 | 非事務(wù)方法A調(diào)用事務(wù)方法B | 事務(wù)生效 |
在同一個類中 | 事務(wù)方法A調(diào)用非事務(wù)方法B | 事務(wù)具有傳播性,事務(wù)生效 |
在同一個類中 | 非事務(wù)方法A調(diào)用事務(wù)方法B | 事務(wù)失效 |
轉(zhuǎn)載:http://www.reibang.com/p/2ab568e7aaf7
3. 編程式事務(wù)TransactionTemplate用法
public class Demo {
@Resource
private TransactionTemplate transactionTemplate;
public void methodA () {
...
// 指定事務(wù)傳播性(可不設(shè)置冯挎,默認(rèn)是`PROPAGATION_REQUIRED`)
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// 指定事務(wù)隔離級別(可不設(shè)置底哥,默認(rèn)是`ISOLATION_DEFAULT`,同數(shù)據(jù)庫隔離級別)
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
transactionTemplate.execute(transactionStatus -> {
methodB();
return Boolean.TRUE;
});
...
}
public void methodB () {
...
}
}
- 事務(wù)傳播行為
1. TransactionDefinition.PROPAGATION_REQUIRED:
如果當(dāng)前存在事務(wù)房官,則加入該事務(wù)趾徽;如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)翰守。這是默認(rèn)值孵奶。
2. TransactionDefinition.PROPAGATION_REQUIRES_NEW:
創(chuàng)建一個新的事務(wù),如果當(dāng)前存在事務(wù)蜡峰,則把當(dāng)前事務(wù)掛起拒课。
3. TransactionDefinition.PROPAGATION_SUPPORTS:
如果當(dāng)前存在事務(wù),則加入該事務(wù)事示;如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行僻肖。
4. TransactionDefinition.PROPAGATION_NOT_SUPPORTED:
以非事務(wù)方式運(yùn)行肖爵,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起臀脏。
5. TransactionDefinition.PROPAGATION_NEVER:
以非事務(wù)方式運(yùn)行劝堪,如果當(dāng)前存在事務(wù),則拋出異常揉稚。
6. TransactionDefinition.PROPAGATION_MANDATORY:
如果當(dāng)前存在事務(wù)秒啦,則加入該事務(wù);如果當(dāng)前沒有事務(wù)搀玖,則拋出異常余境。
7. TransactionDefinition.PROPAGATION_NESTED:
如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運(yùn)行;
如果當(dāng)前沒有事務(wù)芳来,則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED含末。
- 事務(wù)的隔離級別
1. @Transactional(isolation = Isolation.READ_UNCOMMITTED):讀取未提交數(shù)據(jù)(會出現(xiàn)臟讀,
不可重復(fù)讀) 基本不使用
2. @Transactional(isolation = Isolation.READ_COMMITTED):讀取已提交數(shù)據(jù)(會出現(xiàn)不可重復(fù)讀和幻讀)
3. @Transactional(isolation = Isolation.REPEATABLE_READ):可重復(fù)讀(會出現(xiàn)幻讀)
4. @Transactional(isolation = Isolation.SERIALIZABLE):串行化