1

我已经配置了一个应用程序来使用MyBatis-Spring,我想连接到多个数据库。

为此,在我的applicationContext.xml中,我定义了一个数据源、一个事务管理器 ( org.springframework.jdbc.datasource.DataSourceTransactionManager )、一个 Sql 会话工厂 ( org.mybatis.spring.SqlSessionFactoryBean ) 和一个 MapperScannerConfigurer ( org.mybatis .spring.mapper.MapperScannerConfigurer)为它们中的每一个。

然后,在我的服务类中,我想在同一个方法中对多个数据库执行 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 注释?

提前致谢。

4

1 回答 1

0

我在这里找到了@RisingDragon的解决方案:

“如果你是从另一个本地方法调用它,那么它将不起作用,因为 spring 无法知道它被调用并启动事务。

如果您通过使用包含 insertNotes() 方法的类的自动装配对象从另一个类的方法调用它,那么它应该可以工作。”

就我而言,我使用一些@Transactional 方法(例如我的代码中的insertUser)创建了第二个类(例如RisingDragom´s NoteClass),然后回滚工作!这第二个类出现在调试器中,尾部为"$$EnhancedByCGLib"

但是,如果您需要在不同数据库中包含多个步骤的方法,则应应用另一个“自定义”回滚......回滚只是按方法应用,而不是整个过程,因此肯定应该“手动”恢复一些数据在任何步骤失败的情况下。

于 2013-07-16T06:56:45.463 回答