Spring Boot的子項目Spring data JPA配置多數據源的那些坑兒

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是對的,但是還是有些地方不對。

繼續(xù)找原因:

把有問題的源碼貼出來看看:

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)?

繼續(xù)往下看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

錯誤發(fā)生的地方進一步鎖定在?'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

成功!


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容