异常描述
Spring Boot 多租户结构中,Hibernate ddl-auto 无法更新所有的 schema,只能更新最后一个租户的数据库 schema。
解决方案
@Configuration
public class AutoDDLConfig {
private final JpaProperties jpaProperties;
private final TenantDatabaseConfigQueryService tenantDatabaseConfigQueryService;
public AutoDDLConfig(JpaProperties jpaProperties,
TenantDatabaseConfigQueryService tenantDatabaseConfigQueryService) {
this.jpaProperties = jpaProperties;
this.tenantDatabaseConfigQueryService = tenantDatabaseConfigQueryService;
}
@Bean
public void autoDDL() {
Set<TenantDatabaseConfig> tenantDatabaseConfigs = tenantDatabaseConfigQueryService.getAll();
for (TenantDatabaseConfig tenantDatabaseConfig : tenantDatabaseConfigs) {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(tenantDatabaseConfig.getDriverClassName());
dataSource.setSchema(tenantDatabaseConfig.getIdCode());
dataSource.setUrl(tenantDatabaseConfig.getUrl());
dataSource.setUsername(tenantDatabaseConfig.getUsername());
dataSource.setPassword(tenantDatabaseConfig.getPassword());
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource);
emfBean.setPackagesToScan("com.xxx.common.model", "com.xxx.wechat");
emfBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emfBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
Map<String, Object> hibernateProps = new LinkedHashMap<>(jpaProperties.getProperties());
hibernateProps.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5InnoDBDialect");
hibernateProps.put(Environment.HBM2DDL_AUTO, "update");
hibernateProps.put(Environment.PHYSICAL_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
hibernateProps.put(Environment.IMPLICIT_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
hibernateProps.put(Environment.ENABLE_LAZY_LOAD_NO_TRANS, true);
hibernateProps.put(Environment.DEFAULT_SCHEMA, tenantDatabaseConfig.getIdCode());
emfBean.setJpaPropertyMap(hibernateProps);
emfBean.setPersistenceUnitName(dataSource.toString());
emfBean.afterPropertiesSet();
}
}
}