在Spring启动应用程序中未在多个数据库中创建表
我正在开发spring boot多租赁应用程序。 我已经配置了多个数据源,如下所示:
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
@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 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
@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
@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 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)是否有更好的方法使用弹簧启动配置多租赁应用程序以获得更好的性能?
正如@Alex所说,您需要不同的EntityManagers,TransactionManager和Datasources。 我就是这样做的
@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
上使用@Primary
(无关紧要)。 另一个需要注意的是,确保Repository类位于所有三个数据库的不同包中。
您需要2个不同的持久性工厂,而不是一个,每个工厂应为不同的数据源生成不同的EntityManagers。 此外,每个实体映射都应标记为仅与一个实体管理器一起使用。 请在此处查看完整解
- 表每子类inheritance关系:如何在不加载任何子类的情况下查询Parent类??? (hibernate)
- JavaFX + Hibernate(JPA)持久性+ Derby DB
- Hibernate 5.2.7 – java.lang.NoSuchMethodError:org.hibernate.engine.spi.SessionFactoryImplementor.getProperties()Ljava / util / Map;
- 多用户数据源 – Spring + Hibernate
- 我可以用hibernate标准调用存储过程吗?
- 需要一个Hibernate中主键@OneToOne映射的示例
- Struts2-Full-Hibernate插件是集成Struts2和Hibernate的标准方法吗?
- 使用Spring Hibernate的Google Appengine Cloud SQL问题
- JPA没有生成“on delete set null”FK限制