对不起,我的英语不好。我为AbstractRoutingDataSource编写了实现:
public class DatabaseRoutingDataSource extends AbstractRoutingDataSource{ @Override protected Object determineCurrentLookupKey() { return DatabaseContextHolder.getDatabaseType(); } }
我创建了用于在数据库之间进行切换的新类:
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为:
public enum DatabaseType { MAIN, BACKUP }
在我的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中的数据源时:
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')"); }
首次执行getJdbcTemplate()时,一次调用一次defineCurrentLookupKey(),并且数据源不会切换。
Spring JDBC事务的事务管理的一部分是在事务开始时将连接绑定到线程。在事务结束且连接未绑定之前, 对同一数据源的 每个持久性操作都将使用相同的连接。因为您使用单个数据源来掩盖其他两个数据源,所以您只会获得一个连接。如果显式使用了两个单独的数据源,则每个都将被视为单独的资源,并且将启动单独的连接并将其绑定到每个线程。有关将JdbcDaoSupport和JdbcTemplate与事务一起使用的信息,请至少参阅参考指南中的“使资源与事务同步”。