多数据源多重访问中的java数据源路由器问题
我在三个不同的数据源中使用数据源路由启动了ProjectSpring
这是我的配置:
@Configuration
@EnableCaching
public class CachingConfiguration extends CachingConfigurerSupport {
@Override
public KeyGenerator keyGenerator() {
return new EnvironmentAwareCacheKeyGenerator();
}
}
--
public class DatabaseContextHolder {
private static final ThreadLocal<DatabaseEnvironment> CONTEXT =
new ThreadLocal<>();
public static void set(DatabaseEnvironment databaseEnvironment) {
CONTEXT.set(databaseEnvironment);
}
public static DatabaseEnvironment getEnvironment() {
return CONTEXT.get();
}
public static void clear() {
CONTEXT.remove();
}
}
--
@Configuration
@EnableJpaRepositories(basePackageClasses = UsuarioRepository.class,
entityManagerFactoryRef = "customerEntityManager",
transactionManagerRef = "customerTransactionManager")
@EnableTransactionManagement
public class DatasourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.ciclocairu.datasource")
public DataSource ciclocairuDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.palmas.datasource")
public DataSource palmasDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.megabike.datasource")
public DataSource megabikeDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@Primary
public DataSource customerDataSource() {
DataSourceRouter router = new DataSourceRouter();
final HashMap<Object, Object> map = new HashMap<>(3);
map.put(DatabaseEnvironment.CICLOCAIRU, ciclocairuDataSource());
map.put(DatabaseEnvironment.PALMAS, palmasDataSource());
map.put(DatabaseEnvironment.MEGABIKE, megabikeDataSource());
router.setTargetDataSources(map);
return router;
}
@Autowired(required = false)
private PersistenceUnitManager persistenceUnitManager;
@Bean
@Primary
@ConfigurationProperties("spring.jpa")
public JpaProperties customerJpaProperties() {
return new JpaProperties();
}
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean customerEntityManager(
final JpaProperties customerJpaProperties) {
EntityManagerFactoryBuilder builder =
createEntityManagerFactoryBuilder(customerJpaProperties);
return builder.dataSource(customerDataSource()).packages(Users.class)
.persistenceUnit("customerEntityManager").build();
}
@Bean
@Primary
public JpaTransactionManager customerTransactionManager(
@Qualifier("customerEntityManager") final EntityManagerFactory factory) {
return new JpaTransactionManager(factory);
}
private JpaVendorAdapter createJpaVendorAdapter(
JpaProperties jpaProperties) {
AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(jpaProperties.isShowSql());
adapter.setDatabase(jpaProperties.getDatabase());
adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
//adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
return adapter;
}
private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(
JpaProperties customerJpaProperties) {
JpaVendorAdapter jpaVendorAdapter =
createJpaVendorAdapter(customerJpaProperties);
return new EntityManagerFactoryBuilder(jpaVendorAdapter,
customerJpaProperties.getProperties(), this.persistenceUnitManager);
}
}
--
public class DataSourceRouter extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
if(DatabaseContextHolder.getEnvironment() == null)
DatabaseContextHolder.set(DatabaseEnvironment.CICLOCAIRU);
return DatabaseContextHolder.getEnvironment();
}
}
--
public class EnvironmentAwareCacheKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
String key = DatabaseContextHolder.getEnvironment().name() + "-" + (
method == null ? "" : method.getName() + "-") + StringUtils
.collectionToDelimitedString(Arrays.asList(params), "-");
return key;
}
}
我使用 DatabaseContextHolder。set(DatabaseEnvironment.CICLOCAIRU)
转到问题:
例如,不同数据源中的两个用户:1和2
如果一个用户使用datasource 1并发送请求,
另一个用户使用datasource 2,
您的下一个请求不是数据源2,而是获取数据源1。我认为这个ThreadLocal<DatabaseEnvironment> CONTEXT =
new ThreadLocal<>();
是请求的专用项,但事实似乎并非如此
如果这不清楚,我很抱歉
实际上,我需要DataSourceRouter对每个请求都是独占的,并且一个请求不能在另一个请求中插入
我认为DatasourceRouter是错误的,还是我的代码不好
# 1 楼答案
问题的出现可能是因为服务器线程池:您有给定数量的线程,每个请求都在它们之间滚动
当服务器回收一个线程时,线程局部变量的值已经从上一个循环中设置好了,因此您需要在每次请求后刷新该值,使线程保持干净状态