不同的txManager具有相同的DAO,希望将ConnectionHolder的连接注入持久性

时间:2015-07-14 08:10:32

标签: java spring transactions

我有一个将数据从一个数据库复制到另一个数据库的应用程序。在两个DB上都安装了相同的DB模式。当我们复制数据时,需要很多业务逻辑。 我们有一个典型的传统实现,包括服务,dao和自定义持久层(没有实体管理器)。

首先,我开始定义两个不同的事务管理器使用的两个数据源。

@Configuration
@Profile("test")
public class TestEnvironment {


    /**
     * Configuration for the database datasource 1
     * 
     * @return
     */
    @Bean(name = { "DataSource1"})
    public DataSource basicDatasource1() {
            ...
    }

    @Bean
    public DataSourceTransactionManager txManagerDB1() {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(basicDatasource1());

        return dataSourceTransactionManager;
    }

    /**
     * Configuration for the database datasource 2
     * 
     * @return
     */
    @Bean(name = { "DataSource2"})
    public DataSource basicDatasource2() {
            ...
    }

    @Bean
    public DataSourceTransactionManager txManagerDB2() {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(basicDatasource2());

        return dataSourceTransactionManager;
    }

}

然后我实现我的服务并通过@Autowired注入我的测试DAO。 我使用相同的DAO(可重入)实现两种方法。我的服务中的这两个方法我用@Transactional注释并分别设置我想要使用的txManager。

@Service
@Primary
public class MyTestServiceImpl extends AbstractHandler implements MyTestService {

    @Autowired
    private TxManagerTestDao txManagerTestDao;

    @Transactional("txManagerDB1")
    public String callToDB1() {
        txManagerTestDao.setTransactionName("txManagerDB1");
        return txManagerTestDao.loadTestBean().getTestString();
    }

    /*
     * Return DB Connection Type
     */
    @Transactional("txManagerDB2")
    public String callToDB2() {
        txManagerTestDao.setTransactionName("txManagerDB2");
        return txManagerTestDao.loadTestBean().getTestString();
    }

}

行txManagerTestDao.setTransactionName(“txManagerDB1”)或txManagerTestDao.setTransactionName(“txManagerDB2”)是我想删除的错误设计。因为,我只需要在DAO层知道我想用什么事务管理器来设置与持久层的活动连接。

我的DAO如下所示:

@Repository
public class TxManagerTestDaoImpl implements TxManagerTestDao {

    private String transactionName;

    @Autowired
    private AutowireCapableBeanFactory autowireBeanFactory;

    public TestBean loadTestBean() {

        DataSourceTransactionManager myTransaction = (DataSourceTransactionManager) autowireBeanFactory.getBean(transactionName);
        ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(myTransaction.getDataSource());

        //conHolder.getConnection() is know the correct connection I have to use due to the @Transactional in my servide layer.
        //HOW CAN I GET WITH A GENERIC WAY THE ACTIVE TRANSACTION MANAGER?

        TestBean testBean = new TestBean();
        testBean.setTestString("myTransaction: '" + myTransaction + "' Connection: '" + conHolder.getConnection() + "'");

        return testBean;
    }

    @Override
    public void setTransactionName(String transactionName) {
        this.transactionName = transactionName;
    }
}   

我想通过@Transactional(“...”)设置活动txManager,就像我在服务层中所做的那样。我将不会以冗余的方式在将来使用txManagerTestDao.setTransactionName(“txManagerDB2”)。 该解决方案非常完美,但对于我们的特殊用例来说并不完美。

如果txManagerDB1或txManagerDB2处于活动状态,是否存在在方法TxManagerTestDaoImpl.loadTestBean()中找到的通用方法? 因此,我需要活动Transaction的活动ConnectionHolder对象。 我将Connection注入到我的持久性中,然后所有类都在同一个Transaction中运行。 DAO和持久层应该是中性的。我们的持久性只是来自SQL的DataMapper。我想/不能使用JPA或类似的框架。

由于

0 个答案:

没有答案