项目中经常会碰到,多个同类型数据库,或者不同类型数据库同时使用的情况。
最近就碰到,springboot 下,使用多个数据库的情形。
具体操作如下:
我用到了jpa和mybatis调用不同数据库的情形,配置三套数据源。
pom配置如下:
org.springframework.boot
spring-boot-starter-data-jpa
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.0.0
org.springframework.boot
spring-boot-starter-security
mysql
mysql-connector-java
runtime
com.alibaba
druid-spring-boot-starter
${druid.version}
application.properties 配置:
#server.port=25004
#spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#spring.datasource.billsystem.db-type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.billsystem.jdbcUrl=jdbc:log4jdbc:mysql://10.0.17.10:3306/uaserver?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
spring.datasource.billsystem.username=root
spring.datasource.billsystem.password=lxdb2019@
spring.datasource.billsystem.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.billsystem.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.billsystem.filters=stat
spring.datasource.billsystem.initial-size=3
spring.datasource.billsystem.max-active=15
spring.datasource.billsystem.max-pool-prepared-statement-per-connection-size=20
spring.datasource.billsystem.max-wait=5000
spring.datasource.billsystem.min-evictable-idle-time-millis=300000
spring.datasource.billsystem.min-idle=3
spring.datasource.billsystem.pool-prepared-statements=true
spring.datasource.billsystem.stat-view-servlet.enabled= true
spring.datasource.billsystem.stat-view-servlet.login-password=123456
spring.datasource.billsystem.stat-view-servlet.login-username=druid
spring.datasource.billsystem.stat-view-servlet.reset-enable=false
spring.datasource.billsystem.stat-view-servlet.url-pattern=/druid/*
spring.datasource.billsystem.test-on-borrow=false
spring.datasource.billsystem.test-on-return=false
spring.datasource.billsystem.test-while-idle=true
spring.datasource.billsystem.time-between-eviction-runs-millis=90000
spring.datasource.billsystem.validation-query=select 1
spring.datasource.billsystem.web-stat-filter.enabled=true
spring.datasource.billsystem.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
spring.datasource.billsystem.web-stat-filter.session-stat-enable=true
spring.datasource.billsystem.web-stat-filter.session-stat-max-count=1000
spring.datasource.billsystem.web-stat-filter.url-pattern=/*
#spring.datasource.nsradius.db-type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.nsradius.jdbcUrl=jdbc:log4jdbc:mysql://10.0.17.10:3306/lxwisdom?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
spring.datasource.nsradius.username=root
spring.datasource.nsradius.password=lxdb2019@
spring.datasource.nsradius.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.nsradius.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.nsradius.filters=stat
spring.datasource.nsradius.initial-size=3
spring.datasource.nsradius.max-active=15
spring.datasource.nsradius.max-pool-prepared-statement-per-connection-size=20
spring.datasource.nsradius.max-wait=5000
spring.datasource.nsradius.min-evictable-idle-time-millis=300000
spring.datasource.nsradius.min-idle=3
spring.datasource.nsradius.pool-prepared-statements=true
spring.datasource.nsradius.stat-view-servlet.enabled= true
spring.datasource.nsradius.stat-view-servlet.login-password=123456
spring.datasource.nsradius.stat-view-servlet.login-username=druid
spring.datasource.nsradius.stat-view-servlet.reset-enable=false
spring.datasource.nsradius.stat-view-servlet.url-pattern=/druid/*
spring.datasource.nsradius.test-on-borrow=false
spring.datasource.nsradius.test-on-return=false
spring.datasource.nsradius.test-while-idle=true
spring.datasource.nsradius.time-between-eviction-runs-millis=90000
spring.datasource.nsradius.validation-query=select 1
spring.datasource.nsradius.web-stat-filter.enabled=true
spring.datasource.nsradius.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
spring.datasource.nsradius.web-stat-filter.session-stat-enable=true
spring.datasource.nsradius.web-stat-filter.session-stat-max-count=1000
spring.datasource.nsradius.web-stat-filter.url-pattern=/*
#spring.datasource.roma.db-type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.roma.jdbcUrl=jdbc:log4jdbc:mysql://10.0.17.10:3306/roma_db?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
spring.datasource.roma.username=root
spring.datasource.roma.password=lxdb2019@
spring.datasource.roma.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.roma.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
spring.datasource.roma.filters=stat
spring.datasource.roma.initial-size=3
spring.datasource.roma.max-active=15
spring.datasource.roma.max-pool-prepared-statement-per-connection-size=20
spring.datasource.roma.max-wait=5000
spring.datasource.roma.min-evictable-idle-time-millis=300000
spring.datasource.roma.min-idle=3
spring.datasource.roma.pool-prepared-statements=true
spring.datasource.roma.stat-view-servlet.enabled= true
spring.datasource.roma.stat-view-servlet.login-password=123456
spring.datasource.roma.stat-view-servlet.login-username=druid
spring.datasource.roma.stat-view-servlet.reset-enable=false
spring.datasource.roma.stat-view-servlet.url-pattern=/druid/*
spring.datasource.roma.test-on-borrow=false
spring.datasource.roma.test-on-return=false
spring.datasource.roma.test-while-idle=true
spring.datasource.roma.time-between-eviction-runs-millis=90000
spring.datasource.roma.validation-query=select 1
spring.datasource.roma.web-stat-filter.enabled=true
spring.datasource.roma.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
spring.datasource.roma.web-stat-filter.session-stat-enable=true
spring.datasource.roma.web-stat-filter.session-stat-max-count=1000
spring.datasource.roma.web-stat-filter.url-pattern=/*
**创建数据源配置类:**配置三个数据源。第一个是主数据源用@ Primary标签(当一个方法有多个实现类时,在方法中注入了多个,@primary可以指定注入哪一个。
@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用
@Autowired @Qualifier(“personDaoBean”) 存在多个实例配合使用)
package com.isszwy.ioc.datasource.common.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class DruidDataSourceConfig {
@Bean(name = "billSystemDataSource")
@Qualifier("billSystemDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.billsystem")
public DataSource billSystemDataSource(){
return DataSourceBuilder.create().build();
}
@Bean(name = "nsradiusDataSource")
@Qualifier("nsradiusDataSource")
@ConfigurationProperties(prefix = "spring.datasource.nsradius")
public DataSource nsradiusDataSource(){
return DataSourceBuilder.create().build();
}
@Bean(name = "romaDataSource")
@Qualifier("romaDataSource")
@ConfigurationProperties(prefix = "spring.datasource.roma")
public DataSource romaDataSource(){
return DataSourceBuilder.create().build();
}
}
数据源1
package com.isszwy.ioc.datasource.common.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "billSystemEntityManagerFactoryBean",
transactionManagerRef = "billSystemTransactionManager",
//设置Repository所在位置
basePackages = {"me.zhengjie.modules.system.repository","com.isszwy.ioc.ua.repository",
"me.zhengjie.modules.monitor.repository","me.zhengjie.repository","me.zhengjie.modules.quartz.repository"})
public class BillSystemDataSourceConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
private HibernateProperties hibernateProperties;
@Autowired
@Qualifier("billSystemDataSource")
private DataSource billSystemDataSource;
@Bean(name = "billSystemEntityManagerFactoryBean")
@Primary
public LocalContainerEntityManagerFactoryBean billSystemEntityManagerFactoryBean(EntityManagerFactoryBuilder builder){
return builder.dataSource(billSystemDataSource)
.properties(getVendorProperties(billSystemDataSource))
//设置实体类所在位置
.packages("com.isszwy.ioc.ua.domain","me.zhengjie.modules.system.domain",
"me.zhengjie.modules.monitor.domain","me.zhengjie.modules.quartz.domain","me.zhengjie.domain")
.persistenceUnit("billSystemPersistenceUnit")
.build();
}
private Map getVendorProperties(DataSource dataSource){
// return jpaProperties.getHibernateProperties(dataSource);
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
/**
* EntityManagerFactory类似于Hibernate的SessionFactory,mybatis的SqlSessionFactory
* 总之,在执行操作之前,我们总要获取一个EntityManager,这就类似于Hibernate的Session,
* mybatis的sqlSession.
* @param builder
* @return
*/
@Bean(name = "billSystemEntityManagerFactory")
public EntityManagerFactory billSystemEntityManagerFactory(EntityManagerFactoryBuilder builder){
return this.billSystemEntityManagerFactoryBean(builder).getObject();
}
/**
* 配置事物管理器
*/
@Bean(name = "billSystemTransactionManager")
public PlatformTransactionManager billSystemTransactionManager(EntityManagerFactoryBuilder builder){
return new JpaTransactionManager(billSystemEntityManagerFactory(builder));
}
}
数据源2
package com.isszwy.ioc.datasource.common.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "nsradiusEntityManagerFactoryBean",
transactionManagerRef = "nsradiusTransactionManager",
//设置Repository所在位置
basePackages = {"me.zhengjie.visual.staticdata.repository"})
public class NsradiusDataSourceConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
private HibernateProperties hibernateProperties;
@Autowired
@Qualifier("nsradiusDataSource")
private DataSource nsradiusDataSource;
@Bean(name = "nsradiusEntityManagerFactoryBean")
public LocalContainerEntityManagerFactoryBean nsradiusEntityManagerFactoryBean(EntityManagerFactoryBuilder builder){
return builder.dataSource(nsradiusDataSource)
.properties(getVendorProperties(nsradiusDataSource))
//设置实体类所在位置
.packages("me.zhengjie.visual.staticdata.domain")
.persistenceUnit("nsradiusPersistenceUnit")
.build();
}
private Map getVendorProperties(DataSource dataSource){
// return jpaProperties.getHibernateProperties(dataSource);
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
/**
* EntityManagerFactory类似于Hibernate的SessionFactory,mybatis的SqlSessionFactory
* 总之,在执行操作之前,我们总要获取一个EntityManager,这就类似于Hibernate的Session,
* mybatis的sqlSession.
*/
@Bean(name = "nsradiusEntityManagerFactory")
public EntityManagerFactory nsradiusEntityManagerFactory(EntityManagerFactoryBuilder builder){
return this.nsradiusEntityManagerFactoryBean(builder).getObject();
}
/**
* 配置事物管理器
*/
@Bean(name = "nsradiusTransactionManager")
public PlatformTransactionManager nsradiusTransactionManager(EntityManagerFactoryBuilder builder){
return new JpaTransactionManager(nsradiusEntityManagerFactory(builder));
}
}
数据源3
package com.isszwy.ioc.datasource.common.config;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "me.zhengjie.roma.statistics.mapper", sqlSessionFactoryRef = "mybatisSessionFactory")
public class RomaDataSourceConfig {
private static final String MAPPER_LOCATION = "classpath*:mybatis/mapper/*.xml";
@Autowired
@Qualifier("romaDataSource")
private DataSource mybatisDataSource;
@Bean(name = "mybatisTransactionManager")
public DataSourceTransactionManager masterTransactionManager() {
return new DataSourceTransactionManager(mybatisDataSource);
}
@Bean(name = "mybatisSessionFactory")
public SqlSessionFactory mybatisSessionFactory() throws Exception {
// 解决查询返回结果含null没有对应字段值问题
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setCallSettersOnNulls(true);
// configuration.setMapUnderscoreToCamelCase(true);
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(mybatisDataSource);
sessionFactory.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources(RomaDataSourceConfig.MAPPER_LOCATION));
sessionFactory.setConfiguration(configuration);
return sessionFactory.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(mybatisSessionFactory());
}
}
注意在数据源1、2、3中配置对应的映射类和repository、或者mapper和mappper.xml的完整路径,才能在正常使用。还有配置主数据源也就是数据源1 的时候要在对应方法使用 @Primary,多数据源必须有一个主数据源,其他的数据源就不要用 @Primary了。