动态数据源路由 [英] Dynamic DataSource Routing
问题描述
对不起,我的英语不好.我为AbstractRoutingDataSource编写了实现:
Sorry for my bad English. I wrote implementation for AbstractRoutingDataSource:
public class DatabaseRoutingDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}
}
然后我创建了用于在数据库之间进行切换的新类:
And I created new class for switching between databases:
public class DatabaseContextHolder {
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<DatabaseType>();
public static void setDatabaseType(DatabaseType databaseType) {
contextHolder.set(databaseType);
}
public static DatabaseType getDatabaseType() {
return (DatabaseType) contextHolder.get();
}
public static void clearDatabaseType() {
contextHolder.remove();
}
}
其中DatabaseType为:
where DatabaseType is:
public enum DatabaseType {
MAIN,
BACKUP
}
在我的beans.xml中:
in my beans.xml:
<bean id="mainDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/jdbc/DBMIDS"/>
</bean>
<bean id="backupDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/jdbc/DBMIDS2"/>
</bean>
<bean id="dataSource" class="DatabaseRoutingDataSource">
<property name="targetDataSources">
<map key-type="DatabaseType">
<entry key="MAIN" value-ref="mainDataSource"/>
<entry key="BACKUP" value-ref="backupDataSource"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="mainDataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<bean id="databaseTarget" class="DatabaseBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="database" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="databaseTarget"/>
<property name="proxyInterfaces">
<value>Database</value>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED,-MyException</prop>
</props>
</property>
</bean>
现在,当我尝试更改DAO中的数据源时:
Now, when I am trying change datasource in my DAO:
public class DatabaseBean extends JdbcDaoSupport implements Database
public void myMethod() {
DatabaseContextHolder.setDatabaseType(DatabaseType.MAIN);
getJdbcTemplate().execute("INSERT INTO test(test) VALUES('test')");
DatabaseContextHolder.setDatabaseType(DatabaseType.BACKUP);
getJdbcTemplate().execute("INSERT INTO test(test) VALUES('test')");
}
determineCurrentLookupKey()在第一次执行getJdbcTemplate()时调用一次,并且数据源不会切换.
determineCurrentLookupKey() called once, when first executed getJdbcTemplate(), and datasource do not switch.
推荐答案
Spring JDBC事务的事务管理的一部分是在事务开始时将连接绑定到线程.在事务结束并且连接解除绑定之前,同一数据源上的每个持久性操作 都将使用相同的连接.因为您使用单个数据源来掩盖其他两个数据源,所以您只会获得一个连接.如果您显式使用了两个单独的数据源,则每个都将被视为单独的资源,并且将启动一个单独的连接并将其绑定到每个线程.参见同步参考指南中的,至少可以提示您将交易与JdbcDaoSupport和JdbcTemplate一起使用时的幕后花絮.
Part of Spring's transaction management for JDBC transactions is to bind the connection to the thread upon a transaction start. Until the transaction ends and the connection is unbound, every persistence operation on the same datasource will use that same connection. Because you're using a single datasource to mask two others, you'll only ever get the one connection. If you explicitly used two separate datasources, each would be seen as a separate resource, and a separate connection would be started and bound to the thread for each. See "Synchronizing resources with transactions" in the reference guide for at least a hint of what's going on under the hood when you use transactions with a JdbcDaoSupport and JdbcTemplate.
这篇关于动态数据源路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!