在 Spring Boot 应用程序中未在多个数据库中创建表 [英] Tables not getting created in multiple databases in spring boot application
问题描述
我正在开发 Spring Boot 多租户应用程序.我已经配置了多数据源,如下所示:
I am working on spring boot multi tenancy application. I have configured multi datasources as shown below :
application.properties
application.properties
spring.multitenancy.datasource1.url=jdbc:mysql://localhost:3306/db1
spring.multitenancy.datasource1.username=root
spring.multitenancy.datasource1.password=****
spring.multitenancy.datasource1.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.multitenancy.datasource2.url=jdbc:mysql://localhost:3306/db2
spring.multitenancy.datasource2.username=root
spring.multitenancy.datasource2.password=****
spring.multitenancy.datasource2.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.multitenancy.datasource3.url=jdbc:mysql://localhost:3306/db3
spring.multitenancy.datasource3.username=root
spring.multitenancy.datasource3.password=****
spring.multitenancy.datasource3.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
DataSourceBasedMultiTenantConnectionProviderImpl.java
DataSourceBasedMultiTenantConnectionProviderImpl.java
@Component
public class DataSourceBasedMultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
private static final long serialVersionUID = 8168907057647334460L;
private static final String DEFAULT_TENANT_ID = "tenant_1";
@Autowired
private DataSource dataSource1;
@Autowired
private DataSource dataSource2;
@Autowired
private DataSource dataSource3;
private Map<String, DataSource> map;
@PostConstruct
public void load() {
map = new HashMap<>();
map.put("tenant_1", dataSource1);
map.put("tenant_2", dataSource2);
map.put("tenant_3", dataSource3);
}
@Override
protected DataSource selectAnyDataSource() {
return map.get(DEFAULT_TENANT_ID);
}
@Override
protected DataSource selectDataSource(String tenantIdentifier) {
return map.get(tenantIdentifier);
}
}
MultitenancyProperties.java
MultitenancyProperties.java
@ConfigurationProperties("spring.multitenancy")
public class MultitenancyProperties {
@NestedConfigurationProperty
private DataSourceProperties datasource1;
@NestedConfigurationProperty
private DataSourceProperties datasource2;
@NestedConfigurationProperty
private DataSourceProperties datasource3;
public DataSourceProperties getDatasource1() {
return datasource1;
}
public void setDatasource1(DataSourceProperties datasource1) {
this.datasource1 = datasource1;
}
public DataSourceProperties getDatasource2() {
return datasource2;
}
public void setDatasource2(DataSourceProperties datasource2) {
this.datasource2 = datasource2;
}
public DataSourceProperties getDatasource3() {
return datasource3;
}
public void setDatasource3(DataSourceProperties datasource3) {
this.datasource3 = datasource3;
}
}
MultiTenancyJpaConfiguration.java
MultiTenancyJpaConfiguration.java
@Configuration
@EnableConfigurationProperties(JpaProperties.class)
public class MultiTenancyJpaConfiguration {
@Autowired
private DataSource dataSource;
@Autowired
private JpaProperties jpaProperties;
@Autowired
private MultiTenantConnectionProvider multiTenantConnectionProvider;
@Autowired
private CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
Map<String, Object> hibernateProps = new LinkedHashMap<>();
hibernateProps.putAll(jpaProperties.getHibernateProperties(dataSource));
hibernateProps.put(Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
hibernateProps.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
hibernateProps.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
hibernateProps.put(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect");
return builder.dataSource(dataSource).packages(HotelEntity.class.getPackage().getName()).properties(hibernateProps).jta(false).build();
}
}
应用启动器
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(MultitenancyProperties.class)
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
当我运行启动应用程序时,所有表都只在第一个数据源中创建.
1) 如何在应用程序启动时在所有数据源中创建表?
2) 如何查看每个数据源打开/关闭的连接?
3) 是否有更好的方法使用 spring boot 配置多租户应用程序以获得更好的性能?
When I run the boot application, all tables are created in only first data source.
1) How can I create tables in all data sources on application startup?
2) How to see connections opened/closed for each of the data sources?
3) Is there a better way of configuring multi tenancy application using spring boot for better performance?
推荐答案
正如@Alex 所说,您需要不同的 EntityManagers、TransactionManager 和 Datasources.这是我的方法
As @Alex said, you need differnt EntityManagers, TransactionManager and Datasources. Here is how I would do it
@Configuration
@EnableJpaRepositories(
entityManagerFactoryRef = "dataSource1EntityManagerFactory",
transactionManagerRef = "dataSource1TransactionManager",
basePackageClasses = dataSource1Repository.class)
public class DataSource1Config extends SqlConfig{// Put all common code in base class SqlConfig. If not remove it
@Bean
@Primary
public DataSource dataSource1() {
//create dataSource using MultitenancyProperties::getDataSource1
}
@Primary
@Bean(name = "dataSource1TransactionManager")
PlatformTransactionManager dataSource1TransactionManager(EntityManagerFactory dataSource1EntityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(dataSource1EntityManagerFactory);
return txManager;
}
@Primary
@Bean(name = "dataSource1EntityManagerFactory")
LocalContainerEntityManagerFactoryBean dataSource1EntityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource1());
em.setPackagesToScan(dataSource1Repository.class.getPackage().getName(), dataSource1ModelClass.class.getPackage().getName());
em.setPersistenceUnitName("dataSource1Db");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
}
您可以像这样创建另外两个类.请记住仅在数据源、事务管理器和实体管理器的一个实例上使用 @Primary
(与哪一个无关).另一个警告是,请确保所有三个数据库的 Repository 类都位于不同的包中.
You can create two other classes like this. Remember to use @Primary
on only one instace of datasource, transactionmanger and entitymanager(doesn't matter which one). Another word of caution, make sure Repository classes are in different packages for all three databases.
这篇关于在 Spring Boot 应用程序中未在多个数据库中创建表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!