Spring Boot Configure e Use Two DataSources

Sono nuovo di Spring e Spring Boot. Come si procederebbe a configurare e utilizzare due origini dati.

Per esempio ecco quello che ho per la prima fonte di dati.

application.properties

#first db spring.datasource.url = [url] spring.datasource.username = [username] spring.datasource.password = [password] spring.datasource.driverClassName = oracle.jdbc.OracleDriver #second db ... 

Classe di applicazione

 @SpringBootApplication public class SampleApplication { private static final Logger logger = LoggerFactory.getLogger(SampleApplication.class); public static void main(String[] args) { SpringApplication.run(SampleApplication.class, args); } @Autowired SampleRepository repo; @PostConstruct public void testDriving(){ logger.debug(repo.findSomeSample("id", "other")); } } 

Come posso modificare application.properties per aggiungere un’altra origine dati? Come posso autowire per essere utilizzato da un repository diverso?

Ecco qui

 #first db spring.datasource.url = [url] spring.datasource.username = [username] spring.datasource.password = [password] spring.datasource.driverClassName = oracle.jdbc.OracleDriver #second db ... spring.secondDatasource.url = [url] spring.secondDatasource.username = [username] spring.secondDatasource.password = [password] spring.secondDatasource.driverClassName = oracle.jdbc.OracleDriver @Bean @Primary @ConfigurationProperties(prefix="spring.datasource") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix="spring.secondDatasource") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } 

Fare riferimento alla documentazione ufficiale


La creazione di più di un’origine dati equivale alla creazione della prima. È ansible contrassegnare uno di essi come @Primary se si utilizza l’autoconfigurazione predefinita per JDBC o JPA (quindi verrà prelevato da eventuali iniezioni @Autowired).

 @Bean @Primary @ConfigurationProperties(prefix="datasource.primary") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix="datasource.secondary") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } 

Aggiornamento 2018-01-07 con Spring Boot 1.5.8.RELEASE

La maggior parte delle risposte non fornisce come utilizzarle (come origine dati stessa e come transazione), solo come configurarle.

Puoi vedere l’esempio eseguibile e alcune spiegazioni in https://www.surasint.com/spring-boot-with-multiple-databases-example/

Ho copiato del codice qui.

Per prima cosa devi impostare application.properties come questa

 #Database database1.datasource.url=jdbc:mysql://localhost/testdb database1.datasource.username=root database1.datasource.password=root database1.datasource.driver-class-name=com.mysql.jdbc.Driver database2.datasource.url=jdbc:mysql://localhost/testdb2 database2.datasource.username=root database2.datasource.password=root database2.datasource.driver-class-name=com.mysql.jdbc.Driver 

Quindi definirli come provider (@Bean) in questo modo:

 @Bean(name = "datasource1") @ConfigurationProperties("database1.datasource") @Primary public DataSource dataSource(){ return DataSourceBuilder.create().build(); } @Bean(name = "datasource2") @ConfigurationProperties("database2.datasource") public DataSource dataSource2(){ return DataSourceBuilder.create().build(); } 

Nota che ho @Bean (name = “datasource1”) e @Bean (name = “datasource2”), quindi puoi usarlo quando abbiamo bisogno di datasource come @Qualifier (“datasource1”) e @Qualifier (“datasource2”), per esempio

 @Qualifier("datasource1") @Autowired private DataSource dataSource; 

Se ti interessa la transazione, devi definire DataSourceTransactionManager per entrambi, come questo:

 @Bean(name="tm1") @Autowired @Primary DataSourceTransactionManager tm1(@Qualifier ("datasource1") DataSource datasource) { DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource); return txm; } @Bean(name="tm2") @Autowired DataSourceTransactionManager tm2(@Qualifier ("datasource2") DataSource datasource) { DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource); return txm; } 

Quindi puoi usarlo come

 @Transactional //this will use the first datasource because it is @primary 

o

 @Transactional("tm2") 

Questo dovrebbe essere sufficiente. Vedi esempio e dettagli nel link sopra.

Ecco la soluzione completa

 #First Datasource (DB1) db1.datasource.url: url db1.datasource.username:user db1.datasource.password:password #Second Datasource (DB2) db2.datasource.url:url db2.datasource.username:user db2.datasource.password:password 

Dal momento che avremo accesso a due diversi database (db1, db2), dobbiamo configurare separatamente ciascuna configurazione di origine dati come:

 public class DB1_DataSource { @Autowired private Environment env; @Bean @Primary public LocalContainerEntityManagerFactoryBean db1EntityManager() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(db1Datasource()); em.setPersistenceUnitName("db1EntityManager"); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); HashMap properties = new HashMap<>(); properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); properties.put("hibernate.show-sql", env.getProperty("jdbc.show-sql")); em.setJpaPropertyMap(properties); return em; } @Primary @Bean public DataSource db1Datasource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName( env.getProperty("jdbc.driver-class-name")); dataSource.setUrl(env.getProperty("db1.datasource.url")); dataSource.setUsername(env.getProperty("db1.datasource.username")); dataSource.setPassword(env.getProperty("db1.datasource.password")); return dataSource; } @Primary @Bean public PlatformTransactionManager db1TransactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory( db1EntityManager().getObject()); return transactionManager; } } 

Seconda origine dati:

 public class DB2_DataSource { @Autowired private Environment env; @Bean public LocalContainerEntityManagerFactoryBean db2EntityManager() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(db2Datasource()); em.setPersistenceUnitName("db2EntityManager"); HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); HashMap properties = new HashMap<>(); properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); properties.put("hibernate.show-sql", env.getProperty("jdbc.show-sql")); em.setJpaPropertyMap(properties); return em; } @Bean public DataSource db2Datasource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName( env.getProperty("jdbc.driver-class-name")); dataSource.setUrl(env.getProperty("db2.datasource.url")); dataSource.setUsername(env.getProperty("db2.datasource.username")); dataSource.setPassword(env.getProperty("db2.datasource.password")); return dataSource; } @Bean public PlatformTransactionManager db2TransactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory( db2EntityManager().getObject()); return transactionManager; } } 

Qui puoi trovare l’esempio completo sul mio blog: Spring Boot con Multiple DataSource Configuration

Ho usato mybatis – stack tecnologico springboot 2.0, soluzione:

 //application.properties - start sp.ds1.jdbc-url=jdbc:mysql://localhost:3306/mydb?useSSL=false sp.ds1.username=user sp.ds1.password=pwd sp.ds1.testWhileIdle=true sp.ds1.validationQuery=SELECT 1 sp.ds1.driverClassName=com.mysql.jdbc.Driver sp.ds2.jdbc-url=jdbc:mysql://localhost:4586/mydb?useSSL=false sp.ds2.username=user sp.ds2.password=pwd sp.ds2.testWhileIdle=true sp.ds2.validationQuery=SELECT 1 sp.ds2.driverClassName=com.mysql.jdbc.Driver //application.properties - end //configuration class @Configuration @ComponentScan(basePackages = "com.mypkg") public class MultipleDBConfig { public static final String SQL_SESSION_FACTORY_NAME_1 = "sqlSessionFactory1"; public static final String SQL_SESSION_FACTORY_NAME_2 = "sqlSessionFactory2"; public static final String MAPPERS_PACKAGE_NAME_1 = "com.mypg.mymapper1"; public static final String MAPPERS_PACKAGE_NAME_2 = "com.mypg.mymapper2"; @Bean(name = "mysqlDb1") @Primary @ConfigurationProperties(prefix = "sp.ds1") public DataSource dataSource1() { System.out.println("db1 datasource"); return DataSourceBuilder.create().build(); } @Bean(name = "mysqlDb2") @ConfigurationProperties(prefix = "sp.ds2") public DataSource dataSource2() { System.out.println("db2 datasource"); return DataSourceBuilder.create().build(); } @Bean(name = SQL_SESSION_FACTORY_NAME_1) @Primary public SqlSessionFactory sqlSessionFactory1(@Qualifier("mysqlDb1") DataSource dataSource1) throws Exception { System.out.println("sqlSessionFactory1"); SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setTypeHandlersPackage(MAPPERS_PACKAGE_NAME_1); sqlSessionFactoryBean.setDataSource(dataSource1); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBean.getObject(); sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true); sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL); return sqlSessionFactory; } @Bean(name = SQL_SESSION_FACTORY_NAME_2) public SqlSessionFactory sqlSessionFactory2(@Qualifier("mysqlDb2") DataSource dataSource2) throws Exception { System.out.println("sqlSessionFactory2"); SqlSessionFactoryBean diSqlSessionFactoryBean = new SqlSessionFactoryBean(); diSqlSessionFactoryBean.setTypeHandlersPackage(MAPPERS_PACKAGE_NAME_2); diSqlSessionFactoryBean.setDataSource(dataSource2); SqlSessionFactory sqlSessionFactory = diSqlSessionFactoryBean.getObject(); sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true); sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL); return sqlSessionFactory; } @Bean @Primary public MapperScannerConfigurer mapperScannerConfigurer1() { System.out.println("mapperScannerConfigurer1"); MapperScannerConfigurer configurer = new MapperScannerConfigurer(); configurer.setBasePackage(MAPPERS_PACKAGE_NAME_1); configurer.setSqlSessionFactoryBeanName(SQL_SESSION_FACTORY_NAME_1); return configurer; } @Bean public MapperScannerConfigurer mapperScannerConfigurer2() { System.out.println("mapperScannerConfigurer2"); MapperScannerConfigurer configurer = new MapperScannerConfigurer(); configurer.setBasePackage(MAPPERS_PACKAGE_NAME_2); configurer.setSqlSessionFactoryBeanName(SQL_SESSION_FACTORY_NAME_2); return configurer; } } 

Nota: 1) @Primary -> @primary

2) —. “Jdbc-url” nelle proprietà -> Dopo la migrazione di Spring Boot 2.0: jdbcUrl è richiesto con driverClassName

 # Here '1stDB' is the database name spring.datasource.url=jdbc:mysql://localhost/A spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver # Here '2ndDB' is the database name spring.second-datasourcee.url=jdbc:mysql://localhost/B spring.second-datasource.username=root spring.second-datasource.password=root spring.second-datasource.driver-class-name=com.mysql.jdbc.Driver @Bean @Primary @ConfigurationProperties(prefix = "spring.datasource") public DataSource firstDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "spring.second-datasource") public DataSource secondDataSource() { return DataSourceBuilder.create().build(); }