Seems like you could implement a multi-tenant approach, topic I covered in a blog post a few months ago: Multi-tenant applications using Spring Boot, JPA, Hibernate and Postgres
The steps to configure the persistence layer for multitenancy support includes:
- Hibernate, JPA and datasources properties. Something like:
application.yml
...
multitenancy:
dvdrental:
dataSources:
-
tenantId: TENANT_01
url: jdbc:postgresql://172.16.69.133:5432/db_dvdrental
username: user_dvdrental
password: changeit
driverClassName: org.postgresql.Driver
-
tenantId: TENANT_02
url: jdbc:postgresql://172.16.69.133:5532/db_dvdrental
username: user_dvdrental
password: changeit
driverClassName: org.postgresql.Driver
...
I used a properties file to store tenants data but this could be adapted to store tenant information in a kind of master DB.
MultiTenantJpaConfiguration.java
...
@Configuration
@EnableConfigurationProperties({ MultiTenantDvdRentalProperties.class, JpaProperties.class })
@ImportResource(locations = { "classpath:applicationContent.xml" })
@EnableTransactionManagement
public class MultiTenantJpaConfiguration {
@Autowired
private JpaProperties jpaProperties;
@Autowired
private MultiTenantDvdRentalProperties multiTenantDvdRentalProperties;
...
}
MultiTenantDvdRentalProperties.java
...
@Configuration
@ConfigurationProperties(prefix = "multitenancy.dvdrental")
public class MultiTenantDvdRentalProperties {
private List<DataSourceProperties> dataSourcesProps;
// Getters and Setters
public static class DataSourceProperties extends org.springframework.boot.autoconfigure.jdbc.DataSourceProperties {
private String tenantId;
// Getters and Setters
}
}
MultiTenantJpaConfiguration.java
...
public class MultiTenantJpaConfiguration {
...
@Bean(name = "dataSourcesDvdRental" )
public Map<String, DataSource> dataSourcesDvdRental() {
...
}
...
}
- Entity manager factory bean
MultiTenantJpaConfiguration.java
...
public class MultiTenantJpaConfiguration {
...
@Bean
public MultiTenantConnectionProvider multiTenantConnectionProvider() {
...
}
@Bean
public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() {
...
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(MultiTenantConnectionProvider multiTenantConnectionProvider,
CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
...
}
...
}
MultiTenantJpaConfiguration.java
...
public class MultiTenantJpaConfiguration {
...
@Bean
public EntityManagerFactory entityManagerFactory(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
...
}
@Bean
public PlatformTransactionManager txManager(EntityManagerFactory entityManagerFactory) {
...
}
...
}
- Spring Data JPA and transaction support configuration
applicationContent.xml
...
<jpa:repositories base-package="com.asimio.dvdrental.dao" transaction-manager-ref="txManager" />
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
...
ActorDao.java
public interface ActorDao extends JpaRepository<Actor, Integer> {
}
Depending on your needs something like this could be done:
...
@Autowired
private ActorDao actorDao;
...
DvdRentalTenantContext.setTenantId("TENANT_01");
this.actorDao.findOne(...);
...
// Or
DvdRentalTenantContext.setTenantId("TENANT_02");
this.actorDao.save(...);
...
Setting the tenantId could be done in a servlet filter / Spring MVC interceptor / thread that is going to execute the JPA operation, etc.
Again, a detailed explanation and source code could be found at: Multi-tenant applications using Spring Boot, JPA, Hibernate and Postgres