之前的文章介绍了SpringBoot下整合Hibernate,详见:https://blog.terrynow.com/2021/07/08/springboot-integrate-hibernate-include-transaction-how-to/
一般来说是针对单个数据源(数据库)的,不过有时候,需求是要让SpringBoot接多个数据库(也可能是不同的类型的数据库)
实现方法
我们假设会连接2个数据源,一个是默认的(名字就是dataSource),另一个dataSource02,首先在SpringBoot下配置如下(注意默认的dataSource需要加@Primary,另外还需要配置sessionFactory和transactionManager)
MyManageApplication.java
import com.zaxxer.hikari.HikariDataSource; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; import org.springframework.orm.hibernate5.HibernateTransactionManager; import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; import java.util.Properties; // 排除 DataSource, JPARepositories, HibernateJpa 的自动配置 @SpringBootApplication(exclude = { // DataSourceAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) // 开启事务管理 @EnableTransactionManagement(proxyTargetClass = true) public class MyManageApplication extends SpringBootServletInitializer { @Autowired private Environment env; // @Autowired // DataSourceProperties dataSourceProperties; public static void main(String[] args) { SpringApplication.run(MyManageApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(MyManageApplication.class); } @Bean @ConfigurationProperties(prefix="spring.datasource02") public DataSource dataSource02() { return DataSourceBuilder.create() .type(HikariDataSource.class) // .driverClassName(dataSourceProperties.determineDriverClassName()) // .url(dataSourceProperties.determineUrl()) // .username(dataSourceProperties.determineUsername()) // .password(dataSourceProperties.determinePassword()) .build(); } @Bean @Primary // @Bean(name = "dataSource") @ConfigurationProperties(prefix="spring.datasource") public DataSource getDataSource() { // DriverManagerDataSource dataSource = new DriverManagerDataSource(); // // // See: application.properties // dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name")); // dataSource.setUrl(env.getProperty("spring.datasource.url")); // dataSource.setUsername(env.getProperty("spring.datasource.username")); // dataSource.setPassword(env.getProperty("spring.datasource.password")); // // System.out.println("## getDataSource: " + dataSource); // // return dataSource; // return DataSourceBuilder.create().build(); return DataSourceBuilder.create() .type(HikariDataSource.class) // .driverClassName(dataSourceProperties.determineDriverClassName()) // .url(dataSourceProperties.determineUrl()) // .username(dataSourceProperties.determineUsername()) // .password(dataSourceProperties.determinePassword()) .build(); } @Bean(name = "sessionFactory") public SessionFactory getSessionFactory() throws Exception { Properties properties = new Properties(); // See: application.properties properties.put("hibernate.dialect", env.getProperty("spring.jpa.properties.hibernate.dialect")); properties.put("hibernate.show_sql", env.getProperty("spring.jpa.show-sql")); properties.put("current_session_context_class", env.getProperty("spring.jpa.properties.hibernate.current_session_context_class")); // Fix Postgres JPA Error: // Method org.postgresql.jdbc.PgConnection.createClob() is not yet implemented. // properties.put("hibernate.temp.use_jdbc_metadata_defaults",false); LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); // Package contain entity classes factoryBean.setPackagesToScan("net.leizsoft.pdcgpx.entity"); factoryBean.setDataSource(getDataSource()); factoryBean.setHibernateProperties(properties); factoryBean.afterPropertiesSet(); return factoryBean.getObject(); } @Bean(name = "sessionFactory02") public SessionFactory getSessionFactory02() throws Exception { Properties properties = new Properties(); // See: application.properties properties.put("hibernate.dialect", env.getProperty("spring.jpa.properties.hibernate.dialect")); properties.put("hibernate.show_sql", env.getProperty("spring.jpa.show-sql")); properties.put("current_session_context_class", env.getProperty("spring.jpa.properties.hibernate.current_session_context_class")); // Fix Postgres JPA Error: // Method org.postgresql.jdbc.PgConnection.createClob() is not yet implemented. // properties.put("hibernate.temp.use_jdbc_metadata_defaults",false); LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); // Package contain entity classes factoryBean.setPackagesToScan("com.terrynow.test.entity"); factoryBean.setDataSource(dataSource02()); factoryBean.setHibernateProperties(properties); factoryBean.afterPropertiesSet(); return factoryBean.getObject(); } @Autowired @Primary @Bean public HibernateTransactionManager transactionManager(@Qualifier("sessionFactory") SessionFactory sessionFactory) { return new HibernateTransactionManager(sessionFactory); } @Autowired @Bean public HibernateTransactionManager transactionManager02(@Qualifier("sessionFactory02") SessionFactory sessionFactory) { return new HibernateTransactionManager(sessionFactory); } }
SpringBoot的配置文件如下(只摘抄和数据库相关的部分,当然datasource02也可以使用其他数据库如Oracle的连接)
application.yml
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/db1?allowPublicKeyRetrieval=true&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 username: root password: 123456 datasource02: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:8203/db2?allowPublicKeyRetrieval=true&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 username: root password: 654321 jpa: show-sql: false hibernate: ddl-auto: none properties: hibernate: dialect: org.hibernate.dialect.MySQLDialect current_session_context_class: org.springframework.orm.hibernate5.SpringSessionContext
下面测试要service中调用datasource02
TestServiceImpl.java
@Service("testService") @Transactional(readOnly = false, value = "transactionManager02") @Repository public class TestServiceImpl implements ITestService { @Resource(name = "testDao") private ITestDao testDao; @Override public void test() { System.out.println("applyInfo count: "+testDao.test()); } }
DAO操作类如下(使用了sessionFactory02):
TestDaoImpl.java
@Component("testDao") public class TestDaoImpl implements ITestDao { @Autowired private SessionFactory sessionFactory02; @Override public int test() { NativeQuery nativeQuery = sessionFactory.getCurrentSession().createNativeQuery("select count(*) as cnt from t_test"); nativeQuery.addScalar("cnt", new LongType()); return (Long) nativeQuery.uniqueResult(); } }
文章评论