Есть ли способ отобразить базы данных Mutliple с одинаковыми именами таблиц в Dynami c? - PullRequest
1 голос
/ 18 февраля 2020

Впервые я сталкиваюсь с этой проблемой. Ситуация такова:

У меня более 100 SQL баз данных, каждая из которых соответствует своей компании, и у каждой из них три одинаковые таблицы (одинаковые имена таблиц, одинаковые имена столбцов, одинаковый тип данных столбцов).

Есть ли способ динамически отобразить все эти базы данных?

Под динамически я подразумеваю наличие одного класса, на который я могу ссылаться, и выполняю любую операцию CRUD.

1 Ответ

0 голосов
/ 03 марта 2020

После некоторых исследований я смог увидеть, что я хотел сделать:

По сути, мне нужно было изменить источник данных во время выполнения, для этого я использовал интерфейс среды 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);


    //... 

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...