@Transactional配置事务不生效

配置Spring的@Transactional注解事务后,实际业务操作是会不生效,原因可能有如下:

原因一:工程中有连接多个不同数据源,如:数据库A和数据库B,且具体的业务方法只处理单数据库A或B的数据,需要在调用方法的@Transactional中指定具体的数据库A或B的事务配置

application.xml事物配置,包含A数据库和B数据库事务配置

<!--数据库A事务配置-->
<bean id="aDaTaTransactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="aDataSource" />
</bean>
<bean id="aDataTransactionTemplate"
	class="org.springframework.transaction.support.TransactionTemplate">
	<property name="transactionManager" ref="aDaTaTransactionManager" />
</bean>
	

<!--数据库B事务配置-->
<bean id="bDaTaTransactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="bDataSource" />
</bean>
<bean id="bDataTransactionTemplate"
	class="org.springframework.transaction.support.TransactionTemplate">
	<property name="transactionManager" ref="bDaTaTransactionManager" />
</bean>
@Transactional
public void addUser(User user){
    //...业务逻辑省略
	//此注解事务在业务逻辑发生异常时,数据库A对应的表数据不会回滚
}
@Transactional(value = "aDataTransactionManager", isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class,RuntimeException.class})
public void addUser(User user){
    //...业务逻辑省略
	//此注解事务在业务逻辑发生异常时,数据库A对应的表数据会回滚
}
</bean>

原因二:在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法。如下文章有详细说明。

参考转自:https://blog.csdn.net/clementad/article/details/47339519

另外提一下编程事物的处理方式,场景依实际而来

@Service
public class TestBo{
	
	private static final Logger log = Logger.getLogger(TestBo.class);
	//步骤1
	@Resource(name="mysqlTransactionTemplate")
	//步骤2
	//@Resource(name="sqlserverTransactionTemplate")
	private TransactionTemplate transactionTemplate;
	
	/**
	 * 编程式事务
	 * 特殊复杂的业务,比如业务方法里操作两种不同类型数据库(如mysql和sqlserver),这种场景每种类型的业务处理尽可能简单,
	 * 如下代码步骤1和步骤2执行完之后,目标结果是两种类型数据库的数据都应该是执行前的结果。示例回滚的是步骤1的数据。
	 * 对应的TransactionTemplate应该注入mysqlTransactionTemplate,倘若注入sqlserverTransactionTemplate,步骤1的结果是不会回滚的,"业务谁先注入谁"
	 * 实际业务场景尽可能选择大概率不会出错的业务TransactionTemplate注入,可以保证后面的业务出错前面的基础数据回滚。
	 * 类似这种场景的可能有更多,更复杂的,这里只举个例子,没有特别完善的方法解决这类业务,欢迎大伙留言吐槽更好的解决办法
	 * @return
	 */
	private ResultMessage testTrans(final String param){
		return this.transactionTemplate.execute(new TransactionCallback<ResultMessage>() {
			@Override
			public ResultMessage doInTransaction(TransactionStatus status) {
				try {
					//1、......mysql业务处理成功
					//2、......sqlserver业务处理失败
				} catch (Exception e) {
					status.setRollbackOnly();
					log.error("--->> error.", e);
					return ResultMessage.error(e.getMessage());
				}
			}
		});
	}
	
}