使用Spring MVC和Hibernate动态地在多租户数据库应用程序中添加租户 [英] Add tenant dynamically in multitenant database application using Spring MVC and Hibernate
问题描述
我想动态地添加租户。 >我添加了主控制器来创建主模式,其中包含动态创建的租户记录。
但问题是当我请求创建租户时,它转到 MultitenantConnectionProvider
我在那里创建了数据库,但是在数据库中我想扫描包 com.appointment.schedular.model.tenant
并在ne数据库中创建表。
MasterDatabaseConfig.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages =com.appointment.schedular.dao.master,
entityManagerFactoryRef =masterEntityManager,
transactionManagerRef =masterTransactionManager
)
@ PropertySource(classpath:application.properties)
public class MasterDatabaseConfig {
@Autowired
private Environment springEnvironment;
@Bean(name =masterDataSource)
public DataSource masterDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty(master.datasource.classname));
dataSource.setUrl(springEnvironment.getProperty(master.datasource.url)+?createDatabaseIfNotExist = true);
dataSource.setUsername(springEnvironment.getProperty(master.datasource.user));
dataSource.setPassword(springEnvironment.getProperty(master.datasource.password));
返回dataSource;
$ b $Bean(name =masterEntityManager)
@Primary
public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory(){
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean
= new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(masterDataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setPackagesToScan(new String [] {com.appointment.schedular.model.master});
entityManagerFactoryBean.setJpaProperties(getHibernateProperties());
entityManagerFactoryBean.setPersistenceUnitName(master);
返回entityManagerFactoryBean;
私有属性getHibernateProperties(){
属性properties = new Properties();
properties.put(hibernate.dialect,springEnvironment.getProperty(hibernate.dialect,org.hibernate.dialect.MySQLDialect));
properties.put(hibernate.show_sql,springEnvironment.getProperty(hibernate.show_sql,true));
properties.put(hibernate.format_sql,springEnvironment.getProperty(hibernate.format_sql,true));
properties.put(hibernate.hbm2ddl.auto,springEnvironment.getProperty(hibernate.hbm2ddl.auto,update));
返回属性;
$ b @Bean(name =masterTransactionManager)
public JpaTransactionManager transactionManager(EntityManagerFactory masterEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(masterEntityManager);
返回transactionManager;
$ b $ h $ TenantDatabaseConfig.java
@Configuration
@EnableTransactionManagement
@ComponentScan(com.appointment.schedular.tenant)
@EnableJpaRepositories(
entityManagerFactoryRef =tenantEntityManager,
transactionManagerRef =tenantTransactionManager,
basePackages = {com.appointment.schedular.dao.tenant})
@PropertySource(classpath:application。属性)
public class TenantDatabaseConfig {
@Autowired
private环境springEnvironment;
@Bean
public JpaVendorAdapter jpaVendorAdapter(){
return new HibernateJpaVendorAdapter();
$ b $Bean(name =tenantDataSource)
public DataSource tenantDataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty(tenant.datasource.classname));
dataSource.setUrl(springEnvironment.getProperty(tenant.datasource.url)+xy+?createDatabaseIfNotExist = true);
dataSource.setUsername(springEnvironment.getProperty(tenant.datasource.user));
dataSource.setPassword(springEnvironment.getProperty(tenant.datasource.password));
返回dataSource;
$ b bBean(name =tenantEntityManager)
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
MultiTenantConnectionProvider connectionProvider,
CurrentTenantIdentifierResolver tenantResolver){
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(tenantDataSource());
emfBean.setPackagesToScan(com.appointment.schedular.model.tenant);
emfBean.setJpaVendorAdapter(jpaVendorAdapter());
地图< String,Object> properties = new HashMap<>();
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT,MultiTenancyStrategy.SCHEMA);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER,connectionProvider);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER,tenantResolver);
properties.put(hibernate.ejb.naming_strategy,org.hibernate.cfg.ImprovedNamingStrategy);
properties.put(hibernate.dialect,springEnvironment.getProperty(hibernate.dialect
,org.hibernate.dialect.MySQLDialect));
properties.put(hibernate.show_sql,springEnvironment.getProperty(hibernate.show_sql
,true));
properties.put(hibernate.format_sql,springEnvironment.getProperty(hibernate.format_sql
,true));
properties.put(hibernate.hbm2ddl.auto,springEnvironment.getProperty(hibernate.hbm2ddl.auto
,update));
emfBean.setJpaPropertyMap(properties);
emfBean.setPersistenceUnitName(master);
返回emfBean;
$ b @Bean(name =tenantTransactionManager)
public JpaTransactionManager transactionManager(EntityManagerFactory tenantEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(tenantEntityManager);
返回transactionManager;
$ b MultitenantConnectionProviderImpl.java
@SuppressWarnings(serial)
@Component
@PropertySource(classpath:application.properties)
public class MultiTenantConnectionProviderImpl扩展AbstractDataSourceBasedMultiTenantConnectionProviderImpl实现ApplicationListener< ContextRefreshedEvent> {
@Autowired
私人环境springEnvironment;
@Autowired
私人TenantDao tenantDao;
@Autowired
@Qualifier(tenantDataSource)
DataSource masterDataSource;
$ b $ * / @ @ Autowired
@Qualifier(tenantEntityManager)
EntityManager * /
private final Map< String,DataSource> map = new HashMap<>();
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent){
init();
}
private void init(){
List< Tenant> tenant = tenantDao.findAll(); (租户租户:租户)
{
DataSource genDatasource = constructDataSource(tenant.getTenantKey());
map.put(tenant.getTenantKey(),genDatasource);
$ b $ *
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean
= new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(genDatasource);
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setPackagesToScan(new String [] {com.appointment.schedular.model.tenant});
地图< String,Object> properties = new HashMap<>();
properties.put(hibernate.ejb.naming_strategy,org.hibernate.cfg.ImprovedNamingStrategy);
properties.put(hibernate.dialect,springEnvironment.getProperty(hibernate.dialect
,org.hibernate.dialect.MySQLDialect));
properties.put(hibernate.show_sql,springEnvironment.getProperty(hibernate.show_sql
,true));
properties.put(hibernate.format_sql,springEnvironment.getProperty(hibernate.format_sql
,true));
properties.put(hibernate.hbm2ddl.auto,springEnvironment.getProperty(hibernate.hbm2ddl.auto
,update));
entityManagerFactoryBean.setJpaPropertyMap(properties);
$ b $ private DataSource constructDataSource(String dbName){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty(tenant.datasource.classname));
dataSource.setUrl(springEnvironment.getProperty(tenant.datasource.url)+ dbName +?createDatabaseIfNotExist = true);
dataSource.setUsername(springEnvironment.getProperty(tenant.datasource.user));
dataSource.setPassword(springEnvironment.getProperty(tenant.datasource.password));
尝试{
dataSource.getConnection()。createStatement()。execute(CREATE DATABASE IF NOT EXISTS+ dbName);
} catch(Exception ex){
System.out.println(ex);
}
返回dataSource;
}
@Override
protected DataSource selectAnyDataSource(){
return masterDataSource;
}
@Override
protected DataSource selectDataSource(String key){
return map.get(key);
}
public void addTenant(String tenantKey){
map.put(tenantKey,constructDataSource(tenantKey));
$ / code $ / pre
$ b $ h $ TenantController.java
@Controller
@RequestMapping(/ tenant)
公共类TenantController {
@Autowired
TenantDao tenantRepo;
@Autowired
MultiTenantConnectionProviderImpl multiTenantConnectionProviderImpl;
@SuppressWarnings(rawtypes)
@CrossOrigin
@RequestMapping(value =/,
method = RequestMethod.POST,
$ consumes = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody String registerTenant(@RequestBody Map map)throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
租户租户= mapper.convertValue(地图,Tenant.class);
String tenantKey = tenant.getName()。replaceAll([^ a-zA-Z] +,).toLowerCase()。trim();
可选<租户> priorStored = tenantRepo.findByTenantKey(tenantKey);
String response =对不起您的公司名称(+ tenant.getName()+)+已被使用;
if(!previouslyStored.isPresent()){
tenant.setTenantKey(tenantKey);
tenantRepo.save(租户);
multiTenantConnectionProviderImpl.addTenant(tenantKey);
response =成功注册,您的密钥是+ tenantKey;
返回响应;
}
返回新的ObjectMapper()。writeValueAsString(response);
}
}
解决方案替换您的 MultitenantConnectionProviderImpl.java
与此代码。使用注入服务创建使用配置类的表。
@SuppressWarnings(serial)
@Component
@PropertySource(classpath:application.properties)
public class MultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl implements ApplicationListener< ContextRefreshedEvent>,ServiceRegistryAwareService {
$ b $ @Autowired
private Environment springEnvironment;
@Autowired
私人TenantDao tenantDao;
@Autowired
@Qualifier(dataSource1)
DataSource masterDataSource;
@Autowired
MultiTenantConnectionProvider connectionProvider;
@Autowired
CurrentTenantIdentifierResolver tenantResolver;
@Autowired
TenantDatabaseConfig tenantDatabaseConfig;
private final Map< String,DataSource> map = new HashMap<>();
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent){
init();
}
private void init(){
List< Tenant> tenant = tenantDao.findAll(); (租户租户:租户)
{
map.put(tenant.getTenantKey(),constructDataSource(tenant.getTenantKey()));
$ b $ private DataSource constructDataSource(String dbName){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty(tenant.datasource.classname));
dataSource.setUrl(springEnvironment.getProperty(tenant.datasource.url)+ dbName +?createDatabaseIfNotExist = true);
dataSource.setUsername(springEnvironment.getProperty(tenant.datasource.user));
dataSource.setPassword(springEnvironment.getProperty(tenant.datasource.password));
entityManagerFactory(dataSource,connectionProvider,tenantResolver);
返回dataSource;
$ b $ public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
MultiTenantConnectionProvider connectionProvider,
CurrentTenantIdentifierResolver tenantResolver){
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource);
emfBean.setPackagesToScan(com.appointment.schedular.model.tenant);
emfBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emfBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
地图< String,Object> properties = new HashMap<>();
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT,MultiTenancyStrategy.DATABASE);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER,connectionProvider);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER,tenantResolver);
properties.put(hibernate.ejb.naming_strategy,org.hibernate.cfg.ImprovedNamingStrategy);
properties.put(hibernate.dialect,springEnvironment.getProperty(hibernate.dialect
,org.hibernate.dialect.MySQLDialect));
properties.put(hibernate.show_sql,springEnvironment.getProperty(hibernate.show_sql
,true));
properties.put(hibernate.format_sql,springEnvironment.getProperty(hibernate.format_sql
,true));
properties.put(hibernate.hbm2ddl.auto,springEnvironment.getProperty(hibernate.hbm2ddl.auto
,update));
emfBean.setJpaPropertyMap(properties);
emfBean.setPersistenceUnitName(dataSource.toString());
emfBean.afterPropertiesSet();
//emfBean.setEntityManagerFactoryInterface((EntityMana)emfBean);
//emfBean.setBeanName(\"srgsrohtak);
返回emfBean;
public JpaTransactionManager transactionManager(EntityManagerFactory tenantEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(tenantEntityManager);
transactionManager.afterPropertiesSet();
返回transactionManager;
$ b @Override
public void injectServices(ServiceRegistryImplementor serviceRegistry){
Map lSettings = serviceRegistry.getService(ConfigurationService.class).getSettings();
DataSource localDs =(DataSource)lSettings.get(hibernate.connection.datasource);
masterDataSource = localDs;
}
@Override
protected DataSource selectAnyDataSource(){
return masterDataSource;
}
@Override
protected DataSource selectDataSource(String key){
return map.get(key);
}
public void addTenant(String tenantKey){
map.put(tenantKey,constructDataSource(tenantKey));
}
}
i am developing web application which uses multitenant database configuration.
I want to add tenant dynamically.
I added master controller to create master schema which hold tenant record created dynamically.
but problem is when i request to create tenant it went to MultitenantConnectionProvider
i created database there but in database i want to scan package com.appointment.schedular.model.tenant
and create table in ne database as well.
MasterDatabaseConfig.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.appointment.schedular.dao.master",
entityManagerFactoryRef = "masterEntityManager",
transactionManagerRef = "masterTransactionManager"
)
@PropertySource("classpath:application.properties")
public class MasterDatabaseConfig {
@Autowired
private Environment springEnvironment;
@Bean(name="masterDataSource")
public DataSource masterDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty("master.datasource.classname"));
dataSource.setUrl(springEnvironment.getProperty("master.datasource.url") + "?createDatabaseIfNotExist=true");
dataSource.setUsername(springEnvironment.getProperty("master.datasource.user"));
dataSource.setPassword(springEnvironment.getProperty("master.datasource.password"));
return dataSource;
}
@Bean(name = "masterEntityManager")
@Primary
public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean
= new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(masterDataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setPackagesToScan(new String[]{"com.appointment.schedular.model.master"});
entityManagerFactoryBean.setJpaProperties(getHibernateProperties());
entityManagerFactoryBean.setPersistenceUnitName("master");
return entityManagerFactoryBean;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", springEnvironment.getProperty("hibernate.dialect","org.hibernate.dialect.MySQLDialect"));
properties.put("hibernate.show_sql", springEnvironment.getProperty("hibernate.show_sql", "true"));
properties.put("hibernate.format_sql", springEnvironment.getProperty("hibernate.format_sql", "true"));
properties.put("hibernate.hbm2ddl.auto", springEnvironment.getProperty("hibernate.hbm2ddl.auto", "update"));
return properties;
}
@Bean(name = "masterTransactionManager")
public JpaTransactionManager transactionManager(EntityManagerFactory masterEntityManager) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(masterEntityManager);
return transactionManager;
}
}
TenantDatabaseConfig.java
@Configuration
@EnableTransactionManagement
@ComponentScan("com.appointment.schedular.tenant")
@EnableJpaRepositories(
entityManagerFactoryRef = "tenantEntityManager",
transactionManagerRef = "tenantTransactionManager",
basePackages = {"com.appointment.schedular.dao.tenant"})
@PropertySource("classpath:application.properties")
public class TenantDatabaseConfig {
@Autowired
private Environment springEnvironment;
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
@Bean(name = "tenantDataSource")
public DataSource tenantDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty("tenant.datasource.classname"));
dataSource.setUrl(springEnvironment.getProperty("tenant.datasource.url")+"xy" + "?createDatabaseIfNotExist=true");
dataSource.setUsername(springEnvironment.getProperty("tenant.datasource.user"));
dataSource.setPassword(springEnvironment.getProperty("tenant.datasource.password"));
return dataSource;
}
@Bean(name = "tenantEntityManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
MultiTenantConnectionProvider connectionProvider,
CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(tenantDataSource());
emfBean.setPackagesToScan("com.appointment.schedular.model.tenant");
emfBean.setJpaVendorAdapter(jpaVendorAdapter());
Map<String, Object> properties = new HashMap<>();
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
properties.put("hibernate.dialect", springEnvironment.getProperty("hibernate.dialect"
, "org.hibernate.dialect.MySQLDialect"));
properties.put("hibernate.show_sql", springEnvironment.getProperty("hibernate.show_sql"
, "true"));
properties.put("hibernate.format_sql", springEnvironment.getProperty("hibernate.format_sql"
, "true"));
properties.put("hibernate.hbm2ddl.auto", springEnvironment.getProperty("hibernate.hbm2ddl.auto"
, "update"));
emfBean.setJpaPropertyMap(properties);
emfBean.setPersistenceUnitName("master");
return emfBean;
}
@Bean(name = "tenantTransactionManager")
public JpaTransactionManager transactionManager(EntityManagerFactory tenantEntityManager) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(tenantEntityManager);
return transactionManager;
}
}
MultitenantConnectionProviderImpl.java
@SuppressWarnings("serial")
@Component
@PropertySource("classpath:application.properties")
public class MultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private Environment springEnvironment;
@Autowired
private TenantDao tenantDao;
@Autowired
@Qualifier("tenantDataSource")
DataSource masterDataSource;
/*@Autowired
@Qualifier("tenantEntityManager")
EntityManager*/
private final Map<String, DataSource> map = new HashMap<>();
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
init();
}
private void init() {
List<Tenant> tenants = tenantDao.findAll();
for (Tenant tenant : tenants) {
DataSource genDatasource = constructDataSource(tenant.getTenantKey());
map.put(tenant.getTenantKey(), genDatasource);
/*
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean
= new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(genDatasource);
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setPackagesToScan(new String[]{"com.appointment.schedular.model.tenant"});
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
properties.put("hibernate.dialect", springEnvironment.getProperty("hibernate.dialect"
, "org.hibernate.dialect.MySQLDialect"));
properties.put("hibernate.show_sql", springEnvironment.getProperty("hibernate.show_sql"
, "true"));
properties.put("hibernate.format_sql", springEnvironment.getProperty("hibernate.format_sql"
, "true"));
properties.put("hibernate.hbm2ddl.auto", springEnvironment.getProperty("hibernate.hbm2ddl.auto"
, "update"));
entityManagerFactoryBean.setJpaPropertyMap(properties);
*/
}
}
private DataSource constructDataSource(String dbName) {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty("tenant.datasource.classname"));
dataSource.setUrl(springEnvironment.getProperty("tenant.datasource.url") + dbName+ "?createDatabaseIfNotExist=true");
dataSource.setUsername(springEnvironment.getProperty("tenant.datasource.user"));
dataSource.setPassword(springEnvironment.getProperty("tenant.datasource.password"));
try {
dataSource.getConnection().createStatement().execute("CREATE DATABASE IF NOT EXISTS " + dbName);
} catch (Exception ex) {
System.out.println(ex);
}
return dataSource;
}
@Override
protected DataSource selectAnyDataSource() {
return masterDataSource;
}
@Override
protected DataSource selectDataSource(String key) {
return map.get(key);
}
public void addTenant(String tenantKey) {
map.put(tenantKey, constructDataSource(tenantKey));
}
}
TenantController.java
@Controller
@RequestMapping("/tenant")
public class TenantController {
@Autowired
TenantDao tenantRepo;
@Autowired
MultiTenantConnectionProviderImpl multiTenantConnectionProviderImpl;
@SuppressWarnings("rawtypes")
@CrossOrigin
@RequestMapping(value = "/",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody String registerTenant(@RequestBody Map map) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Tenant tenant = mapper.convertValue(map, Tenant.class);
String tenantKey = tenant.getName().replaceAll("[^a-zA-Z]+", "").toLowerCase().trim();
Optional<Tenant> previouslyStored = tenantRepo.findByTenantKey(tenantKey);
String response="Sorry your company name ("+tenant.getName()+")"+" is already taken";
if (!previouslyStored.isPresent()) {
tenant.setTenantKey(tenantKey);
tenantRepo.save(tenant);
multiTenantConnectionProviderImpl.addTenant(tenantKey);
response = "Successfully registered, your key is " + tenantKey;
return response;
}
return new ObjectMapper().writeValueAsString(response);
}
}
解决方案 Replace your MultitenantConnectionProviderImpl.java
with this code. Use inject service for creating your tables using configuration class.
@SuppressWarnings("serial")
@Component
@PropertySource("classpath:application.properties")
public class MultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl implements ApplicationListener<ContextRefreshedEvent>,ServiceRegistryAwareService {
@Autowired
private Environment springEnvironment;
@Autowired
private TenantDao tenantDao;
@Autowired
@Qualifier("dataSource1")
DataSource masterDataSource;
@Autowired
MultiTenantConnectionProvider connectionProvider;
@Autowired
CurrentTenantIdentifierResolver tenantResolver;
@Autowired
TenantDatabaseConfig tenantDatabaseConfig;
private final Map<String, DataSource> map = new HashMap<>();
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
init();
}
private void init() {
List<Tenant> tenants = tenantDao.findAll();
for (Tenant tenant : tenants) {
map.put(tenant.getTenantKey(), constructDataSource(tenant.getTenantKey()));
}
}
private DataSource constructDataSource(String dbName) {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty("tenant.datasource.classname"));
dataSource.setUrl(springEnvironment.getProperty("tenant.datasource.url") + dbName+"?createDatabaseIfNotExist=true");
dataSource.setUsername(springEnvironment.getProperty("tenant.datasource.user"));
dataSource.setPassword(springEnvironment.getProperty("tenant.datasource.password"));
entityManagerFactory(dataSource,connectionProvider, tenantResolver);
return dataSource;
}
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
MultiTenantConnectionProvider connectionProvider,
CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource);
emfBean.setPackagesToScan("com.appointment.schedular.model.tenant");
emfBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emfBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
Map<String, Object> properties = new HashMap<>();
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
properties.put("hibernate.dialect", springEnvironment.getProperty("hibernate.dialect"
, "org.hibernate.dialect.MySQLDialect"));
properties.put("hibernate.show_sql", springEnvironment.getProperty("hibernate.show_sql"
, "true"));
properties.put("hibernate.format_sql", springEnvironment.getProperty("hibernate.format_sql"
, "true"));
properties.put("hibernate.hbm2ddl.auto", springEnvironment.getProperty("hibernate.hbm2ddl.auto"
, "update"));
emfBean.setJpaPropertyMap(properties);
emfBean.setPersistenceUnitName(dataSource.toString());
emfBean.afterPropertiesSet();
//emfBean.setEntityManagerFactoryInterface((EntityMana)emfBean);
//emfBean.setBeanName("srgsrohtak");
return emfBean;
}
public JpaTransactionManager transactionManager(EntityManagerFactory tenantEntityManager) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(tenantEntityManager);
transactionManager.afterPropertiesSet();
return transactionManager;
}
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
Map lSettings = serviceRegistry.getService(ConfigurationService.class).getSettings();
DataSource localDs = (DataSource) lSettings.get("hibernate.connection.datasource");
masterDataSource = localDs;
}
@Override
protected DataSource selectAnyDataSource() {
return masterDataSource;
}
@Override
protected DataSource selectDataSource(String key) {
return map.get(key);
}
public void addTenant(String tenantKey) {
map.put(tenantKey, constructDataSource(tenantKey));
}
}
这篇关于使用Spring MVC和Hibernate动态地在多租户数据库应用程序中添加租户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!