Весенняя загрузка настройка и использование двух источников данных
Я новичок в Spring и Spring Boot. Как можно было бы настроить и использовать два источника данных.
например вот что у меня есть для первого источника данных.
приложение.свойства
#first db
spring.datasource.url = [url]
spring.datasource.username = [username]
spring.datasource.password = [password]
spring.datasource.driverClassName = oracle.jdbc.OracleDriver
#second db ...
класса
@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"));
}
}
Как изменить приложение.свойства для добавления другого источника данных? Как я могу автоматически использовать его для другого РЕПО?
7 ответов:
держи
#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(); }
создание нескольких источников данных работает так же, как и создание первого. Вы можете пометить один из них как @Primary, если вы используете автоматическую конфигурацию по умолчанию для JDBC или JPA (тогда этот будет выбран любыми инъекциями @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(); }
обновление 2018-01-07 с пружинной загрузкой 1.5.8.Отпустите
большинство ответов не предоставляют, как их использовать (как сам источник данных и как транзакция), только как их настроить.
вы можете увидеть runnable пример и некоторое объяснение в https://www.surasint.com/spring-boot-with-multiple-databases-example/
Я скопировал здесь код.
сначала вы должны установить приложение.свойства, как это
#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затем определите их как поставщиков (@Bean) следующим образом:
@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(); }обратите внимание, что у меня есть @Bean (name= "datasource1") и @Bean(name=" datasource2"), то вы можете использовать его , когда нам нужен источник данных как @Qualifier ("datasource1") и @Qualifier ("datasource2"), например
@Qualifier("datasource1") @Autowired private DataSource dataSource;если вы заботитесь о транзакции, вы должны определить DataSourceTransactionManager для них обоих, например:
@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; }затем вы можете использовать его как
@Transactional //this will use the first datasource because it is @primaryили
@Transactional("tm2")этого должно быть достаточно. Пример и подробности в ссылке выше.
вот полное решение
#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поскольку мы собираемся получить доступ к двум различным базам данных (db1, db2), нам нужно настроить каждую конфигурацию источника данных отдельно, например:
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<string, object=""> 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; } }Второй Источник Данных :
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<string, object=""> 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; } }здесь вы можете найти полный пример на моем блоге : Весенняя загрузка с несколькими конфигурациями источников данных
я использовал MyBatis-springboot 2.0 tech stack, решение:
//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; } }Примечание. : 1)@Primary -> @primary
2)---."JDBC-url" в свойствах ->после миграции Spring Boot 2.0: jdbcUrl требуется с driverClassName
@Primary аннотация при использовании против метода, как показано ниже, работает хорошо, если два источника данных находятся на одном и том же месте БД/сервере.
@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(); }Если источники данных находятся на разных серверах лучше использовать @component вместе с @Primary Примечание. Следующий фрагмент кода хорошо работает на двух разных источниках данных в разных местах
database1.datasource.url = jdbc:mysql://127.0.0.1:3306/db1 database1.datasource.username = root database1.datasource.password = mysql database1.datasource.driver-class-name=com.mysql.jdbc.Driver database2.datasource1.url = jdbc:mysql://192.168.113.51:3306/db2 database2.datasource1.username = root database2.datasource1.password = mysql database2.datasource1.driver-class-name=com.mysql.jdbc.Driver @Configuration @Primary @Component @ComponentScan("com.db1.bean") class DBConfiguration1{ @Bean("db1Ds") @ConfigurationProperties(prefix="database1.datasource") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } } @Configuration @Component @ComponentScan("com.db2.bean") class DBConfiguration2{ @Bean("db2Ds") @ConfigurationProperties(prefix="database2.datasource1") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } }
# 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(); }
Comments