在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切点,对业务代码零侵入,后者对业务代码的侵入比较厉害,但是控制精度更高,这两种模式在开发中可以根据自己的需要选择对应的方式,也可两者混用。
网友评论