Spring启动JPA中的动态数据源

时间:2018-02-12 11:06:00

标签: hibernate spring-boot spring-orm

我有一个应用程序,需要连接到几个不同的架构,但相同类型的所有东西(ORACLE)。决定哪个架构来自UI。

如果用户选择了schema1,那么实体应该在Schema1中保留,如果选择其他,则它应该在选定的其他模式中。

使用Spring启动+ Hibernate与依赖关系" spring-boot-starter-data-jpa"

我创建了一个如下所示的数据源类,以便我可以更改" schemaName"在每次调用数据层之前,在数据源对象中。

@Component
public class SchemaDatasource extends AbstractDataSource {

    private String schemaName;

    @Autowired
    private DSManager dsm;

    public void setSchemaName(String schemaName) {
        this.schemaName = schemaName;
    }

    @Override
    public Connection getConnection() throws SQLException {
        if (schemaName!= null)
            return dsm.getConnection(schemaName);
        else
            return null;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        if (schemaName!= null)
            return dsm.getConnection(schemaName);
        else
            return null;
    }

}

我的问题是在启动期间," HibernateJpaAutoConfiguration"尝试创建sessionfactory。在创建过程中它尝试检查与数据源的连接但是当启动时schemaName为null时,我的SchemaDatasource返回与应用程序引导失败的null连接。

有没有办法解决这个问题。我希望在休眠时可以使用类似于SessionFactory和noopoptions。

如果还有RoutingDatasource,我必须设置defaultDatasource。

Spring boot version: 1.5.9.RELEASE

1 个答案:

答案 0 :(得分:2)

这是我对DataSource的实现

public class DataSourceManager implements DataSource {

    private Map<String, DataSource> dataSources = new HashMap<>();
    private DataSource dataSource;

    public DataSourceManager() {
    }

    public DataSourceManager(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void add(String name, DataSource dataSource) {
        dataSources.put(name, dataSource);
    }

    public void switchDataSource(String name) {
        dataSource = dataSources.get(name);
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return dataSource.getLogWriter();
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
        dataSource.setLogWriter(out);
    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
        dataSource.setLoginTimeout(seconds);
    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return dataSource.getLoginTimeout();
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return dataSource.getParentLogger();
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return dataSource.unwrap(iface);
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return dataSource.isWrapperFor(iface);
    }

    @Override
    public Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return dataSource.getConnection(username, password);
    }
}

这是我的配置

@Configuration
public class DataSourceConfig {

    @Autowired
    private Environment env;

    public DataSource makeDataSource(String name) {
        return DataSourceBuilder.create()
                .driverClassName(env.getProperty("spring.datasource." + name + ".driver-class-name"))
                .url(env.getProperty("spring.datasource." + name + ".url")).build();
    }

    @Bean
    public DataSource dataSource() {
        DataSourceManager dataSourceManager = new DataSourceManager();
        dataSourceManager.add("test1", makeDataSource("test1"));
        dataSourceManager.add("test2", makeDataSource("test2"));
        dataSourceManager.switchDataSource("test1");
        return dataSourceManager;
    }

}

这是application.yml

spring:
  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        dialect: org.hibernate.dialect.H2Dialect
  datasource:
    test1:
      name: test2
      url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
      driver-class-name: org.h2.Driver
      username: h2
      password: h2
    test2:
      name: test1
      url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
      driver-class-name: org.h2.Driver
      username: h2
      password: h2