我有一个将数据从一个数据库复制到另一个数据库的应用程序。在两个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或类似的框架。
由于