由于在springboot2.0中配置多数据源时遇到了很多问题,也看了许多大牛的博客最终解决了问题,于是在这里记录一下我的解决过程。
配置文件中的url应改用jdbc-url
在最开始时我配置的是url,结果会出现 jdbcUrl is required with driverClassName的错误
下面是正确的配置
spring:
datasource:
primary:
jdbc-url: jdbc:mysql://localhost:3306/moneysaller?useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
backup:
jdbc-url: jdbc:mysql://localhost:3306/moneysaller-backup?useUnicode=true&characterEncoding=utf-8&useSSL=true
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
配置类中注意使用@Primary注解
下面是在一个统一配置类中注入主从两个DataSource,注意在主DataSource上标注@Primary注解
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 DataAccessConfiguration {
@Bean
@Primary
@ConfigurationProperties("spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.backup")
public DataSource backupDataSource() {
return DataSourceBuilder.create().build();
}
}
import com.springboot.entity.Order;
import org.springframework.beans.factory.annotation.Qualifier;
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.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager",
basePackages = {"com.springboot.seller.repositorys"})
public class PrimaryConfig {
@Resource
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Resource
private JpaProperties jpaProperties;
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(primaryDataSource)
.packages(Order.class)
.persistenceUnit("primary")
.build();
}
@Primary
@Bean(name = "primaryEntityManager")
public EntityManager primaryEntityManager(EntityManagerFactoryBuilder builder) {
return primaryEntityManagerFactory(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(primaryEntityManagerFactory(builder).getObject());
}
protected Map<String,Object> getVendorProperties(DataSource dataSource){
return jpaProperties.getHibernateProperties(new HibernateSettings());
}
}
import com.springboot.entity.VerificationOrder;
import org.springframework.beans.factory.annotation.Qualifier;
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.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "backupEntityManagerFactory",
transactionManagerRef = "backupTransactionManager",
basePackages = {"com.springboot.seller.repositorysbackup"})
public class BackupConfig {
@Resource
@Qualifier("backupDataSource")
private DataSource backupDataSource;
@Resource
private JpaProperties jpaProperties;
@Bean
public LocalContainerEntityManagerFactoryBean backupEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(backupDataSource)
.packages(VerificationOrder.class)
.persistenceUnit("backup")
.build();
}
@Bean(name = "backupEntityManager")
public EntityManager backupEntityManager(EntityManagerFactoryBuilder builder) {
return backupEntityManagerFactory(builder).getObject().createEntityManager();
}
@Bean(name = "backupTransactionManager")
public PlatformTransactionManager backupTransactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(backupEntityManagerFactory(builder).getObject());
}
protected Map<String,Object> getVendorProperties(DataSource dataSource){
return jpaProperties.getHibernateProperties(new HibernateSettings());
}
}
当未使用@Primary注解时,在控制台会出现类似下面信息,在主配置中的不同的位置缺少注解,都会有类似信息出现,不同之处在于描述的参数个数的不同和方法不同
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method backupEntityManagerFactory in com.springboot.seller.configuration.BackupConfig required a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' in your configuration.
以上实体类Order和VerificationOrder所对应的repository的目录结构如下
以上分开的目的在于避免因主从数据源加载顺序的不同导致其中在某一项被覆盖。