Spring Boot 的spring data JPA配置多数据源项目过程分析:
工程结构:
POM.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
第一个坑儿:
实体管理器和事务管理器配置中:
修改
/* private Map getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}*/
private Map getVendorProperties() {
return jpaProperties.getHibernateProperties(new HibernateSettings());
}
原因:javax.sql.DataSource 不能作为 jpaProperties.getHibernateProperties的参数。
如果你Spring Boot 框架使用1.5.6版本也会报错,
@Autowired
private JpaProperties jpaProperties;
报错说:找不到这个Bean.
第二个坑儿:
at com.potevio.platform.PlatformApplication.main(PlatformApplication.java:10) [classes/:na]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactoryBuilder' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method 'entityManagerFactoryBuilder' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaVendorAdapter' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.JpaVendorAdapter]: Factory method 'jpaVendorAdapter' threw exception; nested exception is java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
百度、goolge了好久:
说什么的都有:1、有人说导入的jar包不对;
2、有人说是因为缺少Herbinate相关的jar包;
我在POM文件中加入:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.1.RELEASE</version>
</dependency>
然后,错误变成了:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactoryHeatMap' defined in class path resource [com/potevio/platform/config/RepositoryHeatMapConfig.class]: Unsatisfied dependency expressed through method 'entityManagerFactoryHeatMap' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactoryBuilder' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method 'entityManagerFactoryBuilder' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaVendorAdapter' defined in class path resource
可见,引入spring-jdbc是对的,但是还是有些地方不对。
继续找原因:
把有问题的源码贴出来看看:
package com.potevio.platform.config;
/**
* @program: platform
* @description: 实体管理器和事务管理器配置
* @author: fengzhenbiao
* @create: 2018-11-28 15:32
**/
import org.springframework.beans.factory.annotation.Autowired;
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.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
/*实体管理工厂引用名称,对应到@Bean注解对应的方法*/
entityManagerFactoryRef="entityManagerFactoryHeatMap",
/*事务管理工厂引用名称,对应到@Bean注解对应的方法*/
transactionManagerRef="transactionManagerHeatMap",
basePackages= {"com.potevio.platform.repository.heatMapRepository" }
)
public class RepositoryHeatMapConfig {
@Autowired
private JpaPropertiesjpaProperties;
@Autowired
@Qualifier("heatMapDS")
private DataSourceheatMapDS;
@Bean(name ="entityManagerHeatMap")
@Primary
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryHeatMap(builder).getObject().createEntityManager();
}
@Bean(name ="entityManagerFactoryHeatMap")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactoryHeatMap (EntityManagerFactoryBuilder builder) {
return builder
.dataSource(heatMapDS)
.properties(getVendorProperties())
.packages("com.potevio.platform.domain.heatMapDomain")//设置实体类所在位置
.persistenceUnit("primaryPersistenceUnit")
.build();
}
private Map getVendorProperties() {
return jpaProperties.getHibernateProperties(new HibernateSettings());
}
/* private Map getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}*/
@Bean(name ="transactionManagerHeatMap")
@Primary
PlatformTransactionManager transactionManagerHeatMap(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryHeatMap(builder).getObject());
}
}
Log记录错误从这里开始:
public LocalContainerEntityManagerFactoryBean entityManagerFactoryHeatMap (EntityManagerFactoryBuilder builder)
继续往下看log
Unsatisfied dependency expressed through method 'entityManagerFactoryBuilder' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaVendorAdapter' defined in class path resource
错误发生的地方进一步锁定在 'entityManagerFactoryBuilder' ,它的第一个参数是什么呢?
看看库里的源码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.orm.jpa;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.sql.DataSource;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
public class EntityManagerFactoryBuilder {
private final JpaVendorAdapter jpaVendorAdapter;
private final PersistenceUnitManager persistenceUnitManager;
private final Map jpaProperties;
private final URL persistenceUnitRootLocation;
private EntityManagerFactoryBuilder.EntityManagerFactoryBeanCallback callback;
public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter, Map jpaProperties, PersistenceUnitManager persistenceUnitManager) {
this(jpaVendorAdapter, jpaProperties, persistenceUnitManager, (URL)null);
}
public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter, Map jpaProperties, PersistenceUnitManager persistenceUnitManager, URL persistenceUnitRootLocation) {
this.jpaVendorAdapter = jpaVendorAdapter;
this.persistenceUnitManager = persistenceUnitManager;
this.jpaProperties =new LinkedHashMap(jpaProperties);
this.persistenceUnitRootLocation = persistenceUnitRootLocation;
}
public EntityManagerFactoryBuilder.Builder dataSource(DataSource dataSource) {
return new EntityManagerFactoryBuilder.Builder(dataSource);
}
public void setCallback(EntityManagerFactoryBuilder.EntityManagerFactoryBeanCallback callback) {
this.callback = callback;
}
@FunctionalInterface
public interface EntityManagerFactoryBeanCallback {
void execute(LocalContainerEntityManagerFactoryBean factory);
}
public final class Builder {
private DataSource dataSource;
private String[] packagesToScan;
private String persistenceUnit;
private Map properties;
private String[] mappingResources;
private boolean jta;
private Builder(DataSource dataSource) {
this.properties =new HashMap();
this.dataSource = dataSource;
}
public EntityManagerFactoryBuilder.Builder packages(String... packagesToScan) {
this.packagesToScan = packagesToScan;
return this;
}
public EntityManagerFactoryBuilder.Builder packages(Class... basePackageClasses) {
Set packages =new HashSet();
Class[] var3 = basePackageClasses;
int var4 = basePackageClasses.length;
for(int var5 =0; var5 < var4; ++var5) {
Class type = var3[var5];
packages.add(ClassUtils.getPackageName(type));
}
this.packagesToScan = StringUtils.toStringArray(packages);
return this;
}
public EntityManagerFactoryBuilder.Builder persistenceUnit(String persistenceUnit) {
this.persistenceUnit = persistenceUnit;
return this;
}
public EntityManagerFactoryBuilder.Builder properties(Map properties) {
this.properties.putAll(properties);
return this;
}
public EntityManagerFactoryBuilder.Builder mappingResources(String... mappingResources) {
this.mappingResources = mappingResources;
return this;
}
public EntityManagerFactoryBuilder.Builder jta(boolean jta) {
this.jta = jta;
return this;
}
public LocalContainerEntityManagerFactoryBean build() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean =new LocalContainerEntityManagerFactoryBean();
if (EntityManagerFactoryBuilder.this.persistenceUnitManager !=null) {
entityManagerFactoryBean.setPersistenceUnitManager(EntityManagerFactoryBuilder.this.persistenceUnitManager);
}
if (this.persistenceUnit !=null) {
entityManagerFactoryBean.setPersistenceUnitName(this.persistenceUnit);
}
entityManagerFactoryBean.setJpaVendorAdapter(EntityManagerFactoryBuilder.this.jpaVendorAdapter);
if (this.jta) {
entityManagerFactoryBean.setJtaDataSource(this.dataSource);
}else {
entityManagerFactoryBean.setDataSource(this.dataSource);
}
entityManagerFactoryBean.setPackagesToScan(this.packagesToScan);
entityManagerFactoryBean.getJpaPropertyMap().putAll(EntityManagerFactoryBuilder.this.jpaProperties);
entityManagerFactoryBean.getJpaPropertyMap().putAll(this.properties);
if (!ObjectUtils.isEmpty(this.mappingResources)) {
entityManagerFactoryBean.setMappingResources(this.mappingResources);
}
URL rootLocation = EntityManagerFactoryBuilder.this.persistenceUnitRootLocation;
if (rootLocation !=null) {
entityManagerFactoryBean.setPersistenceUnitRootLocation(rootLocation.toString());
}
if (EntityManagerFactoryBuilder.this.callback !=null) {
EntityManagerFactoryBuilder.this.callback.execute(entityManagerFactoryBean);
}
return entityManagerFactoryBean;
}
}
}
应该是缺少一个Baen jpaVendorAdapter
@Bean
@Primary
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter =new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setShowSql(false);
adapter.setGenerateDdl(true);
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5Dialect");
return adapter;
}
注意要修改配置文件中的url---->jdbc-url
然后:
考虑配置有问题:
修改:去掉@Primary
成功!