我已经配置了一个应用程序来使用MyBatis Spring,我想连接到多个数据库。
为此,在我的applicationContext.xml中,我为它们中的每一个定义了一个数据源、一个事务管理器(org.springframework.jdbc.datasource.DataSourceTransactionManager)、一个Sql会话工厂(org.mybatis.spring.SqlSessionFactoryBean。
然后,在我的服务类中,我想在同一方法中对多个数据库执行CRUD操作。由于我必须指出正确的交易经理,我已经做了以下评论:
@Service("myServiceDB")
public class MyServiceDB implements MyService {
[...]
@Transactional(value = "TransactionManager1", rollbackFor = MyCustomException.class)
public MyUser multipleMethod(final int idUser) throws MyCustomException {
MyUser myUser = null;
int rowsAffected1 = -1;
int rowsAffected2 = -1;
try {
myUser = this.mapperOne.getById(idUser);
if (myObject != null) {
rowsAffected1 = this.mapperOne.deleteByIdUser(idUser);
}
if (rowsAffected1 == 1) {
insertUser(myUser);
}
} catch (DataAccessException dae) {
throw new MyCustomException(TRANSACTION_ERROR, dae);
}
if ((myUser == null) || (rowsAffected1 != 1)) {
throw new MyCustomException(TRANSACTION_ERROR);
}
return myUser;
}
@Transactional(value = "TransactionManager2", rollbackFor = MyCustomException.class)
public void insertUser(final MyUser myUser) throws MyCustomException{
int rowsAffected = -1;
try {
rowsAffected = this.mapperTwo.insert(myUser);
**throw new MyCustomException();**
} catch (DataAccessException dae) {
throw new MyCustomException(TRANSACTION_ERROR, dae);
}
//if (rowsAffected != 1) {
// throw new MyCustomException(TRANSACTION_ERROR);
//}
}
[...]
}
因此,每个方法都指向其相应的事务管理器。
如果我在插入后的第二个方法中抛出自定义异常,我会正确地回滚第一个方法中的删除。但是,第二个事务管理器执行的插入没有按照我的意愿正确回滚(即用户已插入第二个数据库,但未在第一个数据库中删除)。
我的问题是:
- 有可能实现我想要的吗
- 我应该如何配置@Transactional注释
提前谢谢。
我通过@RisingDragon:在这里找到了解决方案
"如果你从另一个本地方法调用它,那么它将不起作用,因为spring无法知道它被调用了,也无法启动事务。
如果您使用包含insertNotes()方法的类的autowired对象从另一个类的方法调用它,那么它应该可以工作。"
在我的案例中,我用一些@Transactional方法(例如我的代码中的insertUser)创建了第二个类(例如RisingDragom的NoteClass),然后回滚成功了!!第二个类出现在调试器中,尾部为"$$EnhancedByCGLib"。
但是,如果您需要一个在不同数据库中包含多个步骤的方法,则应应用另一个"自定义"回滚。。。回滚只是一种方法一种方法地应用,而不是针对整个过程,因此在任何步骤失败的情况下,肯定应该"手动"恢复一些数据。