问题
I have an application that need to connect to few different schema's but everything of same type (ORACLE). The decision of which schema comes from UI.
if User selects schema1, then entity should persist in Schema1, if selects other, then it should be in the selected other schema.
Am using Spring boot + Hibernate with the dependency "spring-boot-starter-data-jpa"
I have created a datasource class like below so that i can change the "schemaName" in the datasource object everytime before invoking the data layer.
@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;
}
}
My problem is during the startup, the "HibernateJpaAutoConfiguration" tries creating sessionfactory.During creation it tries to check connection with the datasource But as schemaName is null in the startup, my SchemaDatasource returns null connection with which application bootstrap is failed.
is there a way to handle this. Am expecting similar to SessionFactory withnooptions in hibernate.
In case of RoutingDatasource also, i have to set defaultDatasource.
Spring boot version: 1.5.9.RELEASE
回答1:
Here is my implementation of 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);
}
}
Here is my configuration
@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;
}
}
Here is 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
来源:https://stackoverflow.com/questions/48744973/dynamic-datasource-in-spring-boot-jpa