Python 官方文档:入门教程 => 点击学习
目录@Transaction注解导致动态切换更改数据库失效使用场景遇到问题解决@Transactional失效的场景及原理1.@Transactional修饰的方法2.在类内部没有添
当给Controller方法加上@Transaction注解后,动态切换数据源就失效了,原因是每次@Before注解的方法运行之前,protected abstract Object determineCurrentLookupKey();就已经运行了,而这个方法是切换数据源的关键。
其实也算不上解决,就是不要在Controller方法上加事务注解,非要加事务,中间的Service层就不要省了。
为非public方法,这个时候@Transactional会实现。
失败的原理是:@Transactional是基于动态代理来实现的,非public的方法,他@Transactional的动态代理对象信息为空,所以不能回滚。
调用了@Transactional方法时,当你调用是,他也不会回滚
测试代码如下
@Service
public class UserServiceImpl extends BaseServiceImpl<UserEntity> implements UserService {
@Autowired
private UserMapper userMapper;
@Override
@Transactional
public void insertOne() {
UserEntity userEntity = new UserEntity();
userEntity.setUsername("Michael_C_2019");
//插入到数据库
userMapper.insertSelective(userEntity);
//手动抛出异常
throw new IndexOutOfBoundsException();
}
@Override
public void saveOne() {
insertOne();
}
}
失败的原理:@Transactional是基于动态代理对象来实现的,而在类内部的方法的调用是通过this关键字来实现的,没有经过动态代理对象,所以事务回滚失效。
没有在catch代码块里面重新抛出异常,事务也不会回滚。
代码如下:
@Override
@Transactional
public void insertOne() {
try {
UserEntity userEntity = new UserEntity();
userEntity.setUsername("Michael_C_2019");
//插入到数据库
userMapper.insertSelective(userEntity);
//手动抛出异常
throw new IndexOutOfBoundsException();
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
所以在阿里巴巴的Java开发者手册里面有明确规定,在 @Transactional的方法里面捕获了异常,必须要手动回滚,
代码如下:
@Override
@Transactional
public void insertOne() {
try {
UserEntity userEntity = new UserEntity();
userEntity.setUsername("Michael_C_2019");
//插入到数据库
userMapper.insertSelective(userEntity);
//手动抛出异常
throw new IndexOutOfBoundsException();
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
TransactionAspectSupport类里面的invokeWithinTransaction方法
TransactionAspectSupport
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
TransactionAttributeSource tas = this.getTransactionAttributeSource();
TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
PlatfORMTransactionManager tm = this.determineTransactionManager(txAttr);
String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
Object result;
if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
TransactionAspectSupport.ThrowableHolder throwableHolder = new TransactionAspectSupport.ThrowableHolder(null);
try {
result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, (status) -> {
TransactionAspectSupport.TransactionInfo txInfo = this.prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
Object var9;
try {
Object var8 = invocation.proceedWithInvocation();
return var8;
} catch (Throwable var13) {
if (txAttr.rollbackOn(var13)) {
if (var13 instanceof RuntimeException) {
throw (RuntimeException)var13;
}
throw new TransactionAspectSupport.ThrowableHolderException(var13);
}
throwableHolder.throwable = var13;
var9 = null;
} finally {
this.cleanupTransactionInfo(txInfo);
}
return var9;
});
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
} else {
return result;
}
} catch (TransactionAspectSupport.ThrowableHolderException var19) {
throw var19.getCause();
} catch (TransactionSystemException var20) {
if (throwableHolder.throwable != null) {
this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
var20.initApplicationException(throwableHolder.throwable);
}
throw var20;
} catch (Throwable var21) {
if (throwableHolder.throwable != null) {
this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw var21;
}
} else {
TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
result = null;
try {
result = invocation.proceedWithInvocation();
} catch (Throwable var17) {
//异常时,在catch逻辑中回滚事务
this.completeTransactionAfterThrowing(txInfo, var17);
throw var17;
} finally {
this.cleanupTransactionInfo(txInfo);
}
this.commitTransactionAfterReturning(txInfo);
return result;
}
}
他是通过捕获异常然后在catch里面进行事务的回滚的,所以如果你在自己的方法里面catch了异常,catch里面没有抛出新的异常,那么事务将不会回滚。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
--结束END--
本文标题: 解决@Transaction注解导致动态切换更改数据库失效问题
本文链接: https://lsjlt.com/news/134846.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0