После некоторых исследований я смог увидеть, что я хотел сделать:
По сути, мне нужно было изменить источник данных во время выполнения, для этого я использовал интерфейс среды Spring под названием AbstracRoutingDataSource
.
Пример:
Реализация AbstractRoutingDataSource:
public class MultiRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getCurrentDb();
}
}
DatabaseContextHolder:
public class DBContextHolder {
private static final ThreadLocal<DBTypeEnum> contextHolder = new ThreadLocal<>();
public static void setCurrentDb(DBTypeEnum dbType) {
contextHolder.set(dbType);
}
public static DBTypeEnum getCurrentDb() {
return contextHolder.get();
}
public static void clear() {
contextHolder.remove();
}
}
Тип базы данных enum:
public enum DBTypeEnum{
DATASOURCE1("DATASOURCE1"),
DATASOURCE2("DATASOURCE2");
DBTypeEnum(final String dbTypeEnum){
this.dbTypeEnum = dbTypeEnum;
}
private String dbTypeEnum;
public String dbTypeEnum(){
return dbTypeEnum;
}
}
Настройка персистентности:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "base.packages.path",
entityManagerFactoryRef = "multiEntityManager",
transactionManagerRef = "multiTransactionManager"
)
public class PersistenceConfiguration {
private final String PACKAGE_SCAN = "base.package.path";
@Bean(name = "dataSource1")
@ConfigurationProperties("spring.datasource1")
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
}
@Bean(name = "dataSource2")
@ConfigurationProperties("spring.datasource2")
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
@Bean(name = "multiRoutingDataSource")
public DataSource multiRoutingDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DBTypeEnum.DATASOURCE1, dataSource1());
targetDataSources.put(DBTypeEnum.DATASOURCE2, dataSource2());
MultiRoutingDataSource multiRoutingDataSource = new MultiRoutingDataSource();
multiRoutingDataSource.setDefaultTargetDataSource(dataSource1());
multiRoutingDataSource.setTargetDataSources(targetDataSources);
return multiRoutingDataSource;
}
@Bean(name = "multiEntityManager")
public LocalContainerEntityManagerFactoryBean multiEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(multiRoutingDataSource());
em.setPackagesToScan(PACKAGE_SCAN);
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(hibernateProperties());
return em;
}
@Bean(name = "multiTransactionManager")
public PlatformTransactionManager multiTransactionManager() {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
multiEntityManager().getObject());
return transactionManager;
}
@Bean(name = "dbSessionFactory")
public LocalSessionFactoryBean dbSessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(multiRoutingDataSource());
sessionFactoryBean.setPackagesToScan(PACKAGE_SCAN);
sessionFactoryBean.setHibernateProperties(hibernateProperties());
return sessionFactoryBean;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", true);
properties.put("hibernate.format_sql", true);
return properties;
}
}
Затем вам нужно иметь всю информацию о вашей базе данных в файле .properties:
spring.datasource1.jdbcUrl=jdbc:sql:sql-url:3306/datasource1
spring.datasource1.username=username
spring.datasource1.password=password
spring.datasource1.driver-class-name= Driver
spring.datasource2.jdbcUrl=jdbc:sql:sql-url:3306/datasource2
spring.datasource2.username=username
spring.datasource2.password=password
spring.datasource2.driver-class-name= Driver
Затем вам нужно отобразить вашу сущность:
@Entity
@Table(name = "table_name")
@Getter
@Setter
public class MyEntity implements Serializable {
@Id
@Column(name = "ID", columnDefinition = "varchar(17)")
private String id;
//more fields...
}
Я использовал весенний интерфейс CrudRepositories для этой сущности
public interface IMyEntityRepository extends CrudRepository<MyEntity, String> {
}
Наконец, мой контроллер готов изменить источник данных в зависимости от поля JSON в моем запросе.
JSON:
{
"dataSource":"DATASOURCE1"
//more fields ...
}
RESTController:
@PutMapping("/url/{id}")
public ResponseEntity<?> editMyEntity(@RequestBody RequestObject request @PathVariable String id){
DBContextHolder.setCurrentDb(DBTypeEnum.valueOf(request.getDataSource);
iMyEntitiRepository.getMyEntity(id);
//...
}