前言
事務(wù)作用:在數(shù)據(jù)層保障一系列的數(shù)據(jù)庫操作同成功同失敗。
Spring
事務(wù)作用:在數(shù)據(jù)層或業(yè)務(wù)層保障一系列的數(shù)據(jù)庫操作同成功同失敗。
Spring事務(wù)
關(guān)于事務(wù)的使用通過在案例中來講解比較直觀全面。
本文以案例的方式來詳解Spring
事務(wù)。
案例:模擬銀行賬戶之間的轉(zhuǎn)賬業(yè)務(wù)。
需求:實(shí)現(xiàn)兩個賬戶(A,B)之間的轉(zhuǎn)賬操作。
業(yè)務(wù)分析:
- 數(shù)據(jù)層提供基礎(chǔ)操作,指定賬戶減錢(outMoney),指定賬戶加錢(inMoney)。
- 業(yè)務(wù)層提供轉(zhuǎn)賬操作(transfer),調(diào)動減錢與加錢的操作。
- 提供2個賬號和操作金額執(zhí)行轉(zhuǎn)賬操作。
- 基于Spring整合MyBatis環(huán)境搭建上述操作。
結(jié)果分析:
- 程序正常執(zhí)行時,賬戶金額A減B加,沒有問題。
- 程序出現(xiàn)異常后,轉(zhuǎn)賬失敗,但是異常之前操作成功,異常之后操作失敗,整體業(yè)務(wù)失敗。
1. 快速實(shí)現(xiàn)
1.1 在業(yè)務(wù)層接口上添加Spring事務(wù)管理
public interface AccountService {
@Transactional
void transfer(String out, String in, Double money);
}
注意:
Spring
注解式事務(wù)通常添加在業(yè)務(wù)層接口中而不會添加到業(yè)務(wù)層實(shí)現(xiàn)類中,降低耦合。
注解式事務(wù)可以添加到業(yè)務(wù)方法上表示當(dāng)前方法開啟事務(wù),也可以添加到接口上表示當(dāng)前接口所有方法開啟事務(wù)。
1.2 設(shè)置事務(wù)管理器
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
注意:
事務(wù)管理器要根據(jù)實(shí)現(xiàn)技術(shù)進(jìn)行選擇
MyBatis
框架使用的是JDBC
事務(wù)
1.3 開啟注解式事務(wù)驅(qū)動
在Spring
配置類中使用注解@EnableTransactionManagement
開啟事務(wù)驅(qū)動
@Configuration
@ComponentScan({"com.hao.service", "com.hao.dao", "com.hao.aop"})
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}
2. Spring事務(wù)角色
2.1 事務(wù)管理員
發(fā)起事務(wù)方,在Spring
中通常指代業(yè)務(wù)層開啟事務(wù)的方法。
如這里AccountService
中的transfer
方法是事務(wù)管理員。該方法執(zhí)行時會開啟一個事務(wù)。
@Transactional
public void transfer(String out, String in, Double money) {
accountDao.outMoney(out, money);
accountDao.inMoney(in, money);
}
2.1 事務(wù)協(xié)調(diào)員
加入事務(wù)方,在Spring
中通常指代數(shù)據(jù)層方法,也可以是業(yè)務(wù)層方法 。
由于AccountDao
在AccountService
中的transfer
方法中被調(diào)用,而且transfer
開啟了事務(wù),所以這里AccountDao
中的inMoney
和outMoney
方法都是事務(wù)協(xié)調(diào)員。這兩個方法也會開啟相應(yīng)的事務(wù)并加入事務(wù)管理員的事務(wù),這樣來保證整體業(yè)務(wù)的同成功同失敗。
public interface AccountDao {
@Update("update tb_account set money = money + #{money} where name = #{name}")
void inMoney(@Param("name") String name, @Param("money") Double money);
@Update("update tb_account set money = money - #{money} where name = #{name}")
void outMoney(@Param("name") String name, @Param("money") Double money);
}
3. 事務(wù)相關(guān)配置
在@Transactional
注解中的屬性及作用如下圖:
這里主要是屬性rollbackFor
會常用到,因?yàn)?code>Spring事務(wù)并不是對于所有異常都會回滾,通過這個屬性可以設(shè)置必須回滾的異常。比如可以進(jìn)行如下設(shè)置:
public interface AccountService {
@Transactional(rollbackFor = {IOException.class, NullPointerException.class})
void transfer(String out, String in, Double money);
}
4. 事務(wù)傳播行為
上邊我們通過事務(wù)回滾達(dá)到了業(yè)務(wù)同成功同失敗的需求。但是開發(fā)中可能也會遇到不需要事務(wù)管理員中的所有協(xié)調(diào)員都進(jìn)行回滾。
比如在transfer
中增加一個日志打印的業(yè)務(wù),要求無論transfer
是否執(zhí)行成功,都進(jìn)行日志打印。
public interface LogService {
void log(String out, String in, Double money);
}
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private LogService logService;
@Override
public void transfer(String out, String in, Double money) {
try {
accountDao.outMoney(out, money);
int i = 10 / 0;
accountDao.inMoney(in, money);
} finally {
logService.log(out, in, money);
}
}
}
這么寫看起來沒什么問題,但是當(dāng)出現(xiàn)異常進(jìn)行回滾時,LogService
也會進(jìn)行回滾,這樣就無法記錄當(dāng)次操作。
這就要用到事務(wù)傳播行為,即事務(wù)協(xié)調(diào)員對事務(wù)管理員所攜帶事務(wù)的處理態(tài)度。
需要在LogService
的log
方法上增加事務(wù)注解并設(shè)置propagation = Propagation.REQUIRES_NEW
,如下:
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out, String in, Double money) {
logDao.log("轉(zhuǎn)賬操作由" + out + "到" + in + ",金額:" + money);
}
}
該設(shè)置意思是LogService
的log
方法會開啟新的事務(wù),不加入事務(wù)管理員。這樣無論事務(wù)管理員的事務(wù)如何回滾,都不會影響LogService
的log
方法的執(zhí)行。
關(guān)于事務(wù)傳播行為屬性有如下類型:
可以根據(jù)需求進(jìn)行相應(yīng)的設(shè)置。
總結(jié)
以上就是關(guān)于Spring
事務(wù)的全部內(nèi)容。
如果有什么問題,我們可以一起交流討論解決。
最后,希望可以幫助到有需要的碼友。