mar*_*108 5 java spring datasource
我用来AbstractRoutingDataSource动态更改数据源并ThreadLocal设置currentLookupKey。当每个http请求仅使用一个数据源时,它的效果很好。我用JpaRepository
@Component
@Primary
public class RoutingDataSource extends AbstractRoutingDataSource {
@Autowired
private DatabaseMap databaseMap;
@Override
public void afterPropertiesSet() {
setTargetDataSources(databaseMap.getSourcesMap());
setDefaultTargetDataSource(databaseMap.getSourcesMap().get("DEFAULT"));
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}
}
public class DatabaseContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDatabaseType(String string) {
contextHolder.set(string);
}
public static String getDatabaseType() {
return (String) contextHolder.get();
}
public static void clearDatabaseType() {
contextHolder.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试在REST控制器中获取数据时,我仅从一个数据库获取数据。
我的REST控制器中的一些代码
DatabaseContextHolder.setDatabaseType("db1");
//here I get data from db1 as expected
//I use JpaRepository
DatabaseContextHolder.clearDatabaseType();
DatabaseContextHolder.setDatabaseType("db2");
//here I should get data from db2 but get from db1
Run Code Online (Sandbox Code Playgroud)
我尝试调试,看起来Spring在http请求中仅获得一次数据源。
此方法仅被调用一次。
@Override
public Connection getConnection() throws SQLException {
return determineTargetDataSource().getConnection();
}
Run Code Online (Sandbox Code Playgroud)
有什么办法可以迫使Spring改变数据源。
我怀疑你有一个用@Transactional注释注释的方法。在调用该事务方法之前,您首先指定一个数据源键,然后调用事务方法。在事务方法内,您首先调用存储库,它会按照您设置的数据源查找键按预期工作。但是,然后您在事务方法内设置不同的密钥,并调用另一个存储库,它仍然使用您第一次设置的密钥。
DataSource将在启动时由框架选择transaction,因此如果您使用@Transactional注释,那么您在方法内所做的任何切换都是无用的。因为数据源是由为注释创建的代理选择的@Transactional。最好的选择是在非事务性服务中使用分支逻辑或TransactionTemplate使用@Transactional
例如,确保this 中YourRestController没有类级别@Transactional以及没有注释,您将保留它们为您服务。@TransactionalyourRestControllerMethod
@RestController
public class YourRestController {
@Autowired
TransactionalService transactional
public void yourRestControllerMethod(){
//set the datasource look up key to A1 and then
transactional.methodA1();
//change datasource look up key to A2 and then
transactional.methodA2();
}
}
Run Code Online (Sandbox Code Playgroud)
@Service
public class TransactionalService {
@Transactional
public void methodA1(){
}
@Transactional
public void methodA2() {
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
443 次 |
| 最近记录: |