如何让 AbstractRoutingDataSource 正常工作?
Posted
技术标签:
【中文标题】如何让 AbstractRoutingDataSource 正常工作?【英文标题】:How do I get AbstractRoutingDataSource to work properly? 【发布时间】:2016-08-27 05:29:25 【问题描述】:我目前正在尝试在使用 AbstractRoutingDataSource 时创建 Hibernate 会话工厂,但是当它通过 bean 初始化过程时,它会尝试确定查找键。因为我没有设置默认值,所以它将为空。我不想设置默认值 - 我宁愿延迟它,直到我需要创建会话并进行实际查询。
我确实发现其他人也有同样的问题。这是 2005 年的旧存档帖子,描述了我遇到的完全相同的问题。不幸的是,没有真正的答案:
http://forum.spring.io/forum/spring-projects/data/108464-abstractroutingdatasource-not-routing-when-used-with-hibernate-sample-attached
如果我设置一个默认值,一切都会加载“正常” - 但随后更改路由数据源所依赖的线程本地值对使用的数据库的影响为零 - 在那一点上似乎“锁定”了。
有什么想法吗?
【问题讨论】:
您后来解决了这个问题吗?如果是,请分享您的解决方案。 【参考方案1】:AbstractRoutingDataSource
继承数据源。因此它可能会替换必须在启动时配置的数据源。
您可以将数据源列表加载到DataSourceProperties
组件:
@Component
@ConfigurationProperties(prefix = "tenants")
public class DataSourceProperties
private Map <Object, Object> datasources = new LinkedHashMap <>();
public Map<Object, Object> getDatasources()
return datasources;
public void setDatasources(Map<String, Map<String, String>> datasources)
datasources
.forEach((key, value) -> this.datasources.put(key, convert(value)));
private DataSource convert(Map <String, String> source)
return DataSourceBuilder.create()
.url(source.get("jdbcUrl"))
.driverClassName(source.get("driverClassName"))
.username(source.get("username"))
.password(source.get("password"))
.build();
创建AbstractRoutingDataSource
:
public class TenantAwareRoutingDataSource extends AbstractRoutingDataSource
@Override
protected Object determineCurrentLookupKey()
return ThreadLocalStorage.getTenantName();
并将您的数据源配置为AbstractRoutingDataSource
:
@Configuration
public class DataSourceConfig
private final DataSourceProperties dataSourceProperties;
public DataSourceConfig(DataSourceProperties dataSourceProperties)
this.dataSourceProperties = dataSourceProperties;
@Bean
public DataSource getDataSource()
TenantAwareRoutingDataSource tenantAwareRoutingDataSource = new TenantAwareRoutingDataSource();
tenantAwareRoutingDataSource.setTargetDataSources(dataSourceProperties.getDatasources());
tenantAwareRoutingDataSource.afterPropertiesSet();
return tenantAwareRoutingDataSource;
您还应该实现ThreadLocalStorage
来存储租户标识符并让 AbstractRoutingDataSource 检索它以确定要使用的数据源。
为了防止 Spring 在启动时自动配置数据源:
spring:
jpa:
open-in-view: false # Get Rid of OIV Warning
show-sql: true
database: postgresql # Do not Auto-Detect the Database
hibernate:
ddl-auto: none # Prevent Hibernate from Automatic Changes to the DDL Schema
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
datasource:
initialization-mode: never # Prevent JPA from trying to Initialize
【讨论】:
以上是关于如何让 AbstractRoutingDataSource 正常工作?的主要内容,如果未能解决你的问题,请参考以下文章