前言
公司项目的一个接口需要调用不同数据库,可惜不会配置。单个数据源的还挺好弄得,但是多个数据源就需要手动配置,在网上看了好多博客,花了3天时间,出了好多错最后终于弄出来了,现在分享一下。
个人建议不要再自己项目上改,容易出错,而且需要按照某个版本的博客代码建立一个小demo,跑通了再适当修改,不然容易错上加错,浪费时间
另外这个数据源配置有点死,不是动态配置的,每个数据源需要建一个配置类,有点麻烦
配置文件
application.properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.jdbc-url=jdbc:mysql://xxxx:3306/xxxx?useSSL=false&characterEncoding=UTF-8&useUnicode=true
spring.datasource.username=xxxxx
spring.datasource.password=xxxxxx
#other
spring.datasource.other.driver-class-name=org.postgresql.Driver
spring.datasource.other.jdbc-url=jdbc:postgresql://123.56.xxx.xxx:3921/kps_development
spring.datasource.other.username=xxxx
spring.datasource.other.password=xxxxx
# third
spring.datasource.third.jdbc-url=jdbc:mysql://47.95.xxx.xxx:8066/basedb?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&autoReconnect=true
spring.datasource.third.username=xxxx
spring.datasource.third.password=xxxxxxxx
spring.datasource.third.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=none
#spring.jpa.open-in-view=true
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.max_fetch_depth=1
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
spring.jpa.properties.hibernate.hbm2ddl=update
#spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
spring.jackson.serialization.fail-on-empty-beans=false
server.port=8081
配置类
DataSourceConfig
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;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Bean(name="dataSource")
@Primary
@ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
@Bean(name="otherDataSource")
@ConfigurationProperties(prefix="spring.datasource.other")
public DataSource otherDataSource(){
return DataSourceBuilder.create().build();
}
@Bean(name="thirdDataSource")
@ConfigurationProperties(prefix="spring.datasource.third")
public DataSource thirdDataSource(){
return DataSourceBuilder.create().build();
}
}
PrimaryDataSourceConfig
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactoryPrimary",
transactionManagerRef="transactionManagerPrimary",
basePackages={"com.star.dao.mysql"}) //注意各个数据源需要映射不同的包
public class PrimaryDataSourceConfig {
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
@Autowired
private JpaProperties jpaProperties;
@Primary
@Bean(name="entityManagerPrimary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder){
return entityManagerFactoryBean(builder).getObject().createEntityManager();
}
@Primary
@Bean(name="entityManagerFactoryPrimary")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder){
return builder
.dataSource(dataSource)
.properties(getProperties())
.packages("com.star.bean.mysql") //对应实体类
.persistenceUnit("primaryPersistentUnit")
.build();
}
public Map<String, String> getProperties(){
Map<String, String> map = jpaProperties.getProperties();
return map;
}
@Primary
@Bean(name="transactionManagerPrimary")
public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder){
return new JpaTransactionManager(entityManagerFactoryBean(builder).getObject());
}
}
OtherDataSourceConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactoryOther",
transactionManagerRef="transactionManagerOther",
basePackages={"com.star.dao.postgresql"})
public class OtherDataSourceConfig {
@Autowired
@Qualifier("otherDataSource")
private DataSource otherDataSource;
@Autowired
private JpaProperties jpaProperties;
@Bean(name="entityManagerOther")
public EntityManager entityManager(EntityManagerFactoryBuilder builder){
return entityManagerFactoryBean(builder).getObject().createEntityManager();
}
@Bean(name="entityManagerFactoryOther")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder){
return builder
.dataSource(otherDataSource)
.properties(getProperties())
.packages("com.star.bean.postgresql")
.persistenceUnit("otherPersistentUnit")
.build();
}
public Map<String, String> getProperties(){
Map<String, String> map = jpaProperties.getProperties();
return map;
}
@Bean(name="transactionManagerOther")
public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder){
return new JpaTransactionManager(entityManagerFactoryBean(builder).getObject());
}
}
ThirdDataSourceConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactoryThird",
transactionManagerRef="transactionManagerThird",
basePackages={"com.star.dao.mysql2"})
public class ThirdDataSourceConfig {
@Autowired
@Qualifier("thirdDataSource")
private DataSource thirdDataSource;
@Autowired
private JpaProperties jpaProperties;
@Bean(name="entityManagerThird")
public EntityManager entityManager(EntityManagerFactoryBuilder builder){
return entityManagerFactoryBean(builder).getObject().createEntityManager();
}
@Bean(name="entityManagerFactoryThird")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder){
return builder
.dataSource(thirdDataSource)
.properties(getProperties())
.packages("com.star.bean.mysql")
.persistenceUnit("thirdPersistentUnit")
.build();
}
public Map<String, String> getProperties(){
Map<String, String> map = jpaProperties.getProperties();
return map;
}
@Bean(name="transactionManagerThird")
public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder){
return new JpaTransactionManager(entityManagerFactoryBean(builder).getObject());
}
}
这里三个数据源的配置几乎一样,只是主数据源多了@Primary。另外就是getProperties()这里需要注意一下,很多版本这里设置不一样,容易出错,我的就是这里报错“字段找不到”,其实实体映射是对的,但是这里配置错了,一直报这样的错误。
测试
dao
public interface BusinessIndexRepository extends JpaRepository<BusinessIndex,Long> {
}
sevice
@Service
public class BusinessIndexService {
@Autowired
BusinessIndexRepository businessIndexRepository;
public BusinessIndex findById(Long id){
BusinessIndex businessIndex = businessIndexRepository.findById(id).orElse(null);
return businessIndex;
}
}
controller
@Slf4j
@RestController
@RequestMapping("/business")
public class BusinessIndexController {
@Autowired
BusinessIndexService businessIndexService;
@RequestMapping("/message")
public String findBusinessIndex(Long id){
BusinessIndex business = businessIndexService.findById(id);
return business.toString();
}
}