在Spring框架中事務的開啟有兩種方式,一種是申明式開啟,一種是編程開啟。申明式開啟即通過xml配置文件配置TransactionManager的形式啟動事務,通過配置AOP切點進行方法的攔截來實現
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 配置事務管理器類 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事務增強(如果管理事務?) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- Aop配置: 攔截哪些方法(切入點表表達式) + 應用上面的事務增強配置 -->
<aop:config>
<aop:pointcut expression="execution(* cn.unicorn.service.DeptService.save(..))" id="pt"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
另一種是通過編程開啟事務,這種方式對業務的代碼的侵入性太強,但是控制粒度更細,如果對事務控制精度有要求可以采取這種模式。下面來看看具體的列子
/**
* 數據源加入事務管理
* @param masterDataSource
* @return
*/
@Bean(name = "transactionManager")
@Primary
public DataSourceTransactionManager masterDataSourceTransactionManager(@Qualifier("masterDataSource") DataSource masterDataSource){
final DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(masterDataSource);
return dataSourceTransactionManager;
}
/**
* 事務管理加入事務模板
* @param transactionManager
* @return
*/
@Bean(name = "transactionTemplate")
@Primary
public TransactionTemplate masteerTransactionTemplate(@Qualifier("transactionManager") DataSourceTransactionManager transactionManager){
final TransactionTemplate transactionTemplate = new TransactionTemplate();
transactionTemplate.setTransactionManager(transactionManager);
transactionTemplate.setIsolationLevelName("ISOLATION_DEFAULT");
transactionTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRED");
return transactionTemplate;
}
@Override
public void addUsers(List<User> users){
TransactionCallback transactionCallback = new TransactionCallback() {
@Nullable
@Override
public Object doInTransaction(TransactionStatus status) {
try {
for (User user : users) {
int i = userMapper.insert(user);
if (i == 1) {
System.out.println("添加成功");
} else {
System.out.println("添加失敗");
}
}
}catch (Exception e){
e.printStackTrace();
System.out.println("出現異常,回滾");
//設置事務回滾
status.setRollbackOnly();
}
return null;
}
};
transactionTemplate.execute(transactionCallback);
}
從兩個例子中可以看到申明式事務和編程式事務的區別,前者通過配置AOP切點,對業務代碼零侵入,后者對業務代碼的侵入比較厲害,但是控制精度更高,這兩種模式在開發中可以根據自己的需要選擇對應的方式,也可兩者混用。