Spring Boot Configure y use dos DataSources

Soy nuevo en Spring y Spring Boot. ¿Cómo se puede configurar y usar dos fonts de datos?

Por ejemplo, esto es lo que tengo para la primera fuente de datos.

application.properties

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

Clase de aplicación

 @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")); } } 

¿Cómo modifico application.properties para agregar otra fuente de datos? ¿Cómo se autoajusta para ser utilizado por un repository diferente?

Aqui tienes

 #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(); } 

Consulte la documentación oficial


Crear más de una fuente de datos funciona igual que crear la primera. Es posible que desee marcar uno de ellos como @Primary si está utilizando la configuración automática predeterminada para JDBC o JPA (entonces esa será recogida por cualquier inyección @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(); } 

Actualización 2018-01-07 con Spring Boot 1.5.8.RELEASE

La mayoría de las respuestas no proporcionan cómo usarlas (como fuente de datos en sí y como transacción), solo cómo configurarlas.

Puede ver el ejemplo ejecutable y alguna explicación en https://www.surasint.com/spring-boot-with-multiple-databases-example/

Copié un código aquí.

Primero debes establecer application.properties como este

 #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 

Luego defínalos como proveedores (@Bean) de esta manera:

 @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(); } 

Tenga en cuenta que tengo @Bean (name = “datasource1”) y @Bean (name = “datasource2”), luego puede usarlo cuando necesitemos datasource como @Qualifier (“datasource1”) y @Qualifier (“datasource2”), por ejemplo

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

Si le importa la transacción, debe definir DataSourceTransactionManager para ambos, así:

 @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; } 

Entonces puedes usarlo como

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

o

 @Transactional("tm2") 

Esto debería ser suficiente. Ver ejemplo y detalle en el enlace de arriba.

Aquí está la solución 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 

Como vamos a tener acceso a dos bases de datos diferentes (db1, db2), debemos configurar cada configuración de fuente de datos por separado, como por ejemplo:

 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; } } 

Segundo origen de datos:

 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; } } 

Aquí puede encontrar el Ejemplo completo en mi blog: Spring Boot con Multiple DataSource Configuration

Utilicé mybatis – springboot 2.0 tech stack, solución:

 //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” en propiedades -> Después de la migración de Spring Boot 2.0: se requiere jdbcUrl 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(); }