动态数据源路由

对不起,我的英语不好。 我为AbstractRoutingDataSource编写了实现:

public class DatabaseRoutingDataSource extends AbstractRoutingDataSource{ @Override protected Object determineCurrentLookupKey() { return DatabaseContextHolder.getDatabaseType(); } } 

我创建了用于在数据库之间切换的新类:

 public class DatabaseContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal(); 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中:

                        Database    PROPAGATION_REQUIRED,-MyException    

现在,当我尝试在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')"); } 

DetermCurrentLookupKey()调用一次,第一次执行getJdbcTemplate()时,数据源不切换。

Spring的JDBC事务事务管理的一部分是在事务开始时将连接绑定到线程。 在事务结束并且连接未绑定之前, 同一数据源上的每个持久性操作都将使用相同的连接。 因为您使用单个数据源来屏蔽其他两个数据源,所以您只能获得一个连接。 如果您明确使用了两个单独的数据源,则每个数据源都将被视为一个单独的资源,并且将启动一个单独的连接并将其绑定到每个数据的线程。 请参阅参考指南中的“使用事务同步资源” ,以便在使用JdbcDaoSupport和JdbcTemplate事务时至少隐藏一些内容。

您应该在方法调用之前调用DatabaseContextHolder.setDatabaseType(DatabaseType.MAIN)。 一旦启动事务,Hibernate会查找连接。 在您的情况下,在DatabaseContextHolder.setDatabaseType(DatabaseType.MAIN)执行之前启动事务。 并且一旦事务已经开始,架构就无法更改。 您的实现是正确的尝试在方法调用之前,即在事务开始之前设置DatabaseType。