spring cloud(boot) 2.x 整合 spring data jpa

版权声明:版权归@小布吉岛所有 https://blog.csdn.net/zx110503/article/details/81285727

最近研究spring cloud 用的是开发工具创建的项目,自动根配置使用最新版的spring cloud 2.0.3版本,整合spring data jpa过程中发生了好多坑,一步一步踩过去,现在将采坑过程写出来,留作记录。

一、首先创建一个父工程,然后使用开发工具创建一个简单的 Eureka server 服务注册中心,如下:

1、application.properties文件的配置:

##=====Eureka注册中心配置=====##
# 服务端口号
server.port=8761
# 服务地址
eureka.instance.hostname=localhost
# 配置是否将自己注册(默认为true)
eureka.client.register-with-eureka=false
# 关闭检索服务(默认为true)
eureka.client.fetch-registry=false
# 访问路径
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

##=====设置服务名=====##
spring.application.name=eureka-server

2、在启动类上加入@EnableEurekaServer的注解,开启Eureka server的一些默认配置;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

至此,一个简单的Eureka server 服务注册中心就配置好了,启动EurekaApplication类中的main()方法,然后看到下图所示的一些信息,就表示启动成功了:

二、创建消费者,即项目的业务模块,spring cloud 的消费者有两个可以选择,Ribbon 和 Feign,选哪个都可以,具体有什么区别,这里不讨论,需要注意的是Ribbon需要注入restTemplate 。嫌麻烦可以使用Feign,本demo 使用的是Feign。

注:此工程的application.properties配置文件:

##=====加载Eureka注册中心=====##
# 注册路径
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
# 注册服务名称
spring.application.name: polymerize-basic

##=====数据库配置=====##
# MySQL数据库驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# MySQL数据库地址
spring.datasource.url=jdbc:mysql://localhost:3306/polymerize
# MySQL数据库用户名
spring.datasource.username=root
# MySQL数据库密码
spring.datasource.password=root

##=====Jpa配置=====##
# 指定jpa连接类型
spring.jpa.database=MYSQL
# 显示后台处理的SQL语句
spring.jpa.show-sql=true
# 项目启动对数据库的操作
spring.jpa.properties.hibernate.hbm2ddl.auto=update

1、使用开发工具创建一个Feign的工程,然后加入spring data jpa 以及 mysql 驱动的依赖包:

<!--jpa-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

2、加入依赖之后,创建相应的service、dao、controller、model 包,然后写一个简单的UserInfoModel.java 实体类:

import javax.persistence.*;
import java.util.Date;

/**
 * Model class for UserInfo
 */
@Entity
@Table(name = "user_info")
public class UserInfoModel {

	//用户ID
	private Integer userId;
	//角色ID
	private Integer roleId;
	//···省略···	

	/**
	 * Get 用户ID
	 */
	@Column(name = "USER_ID")
	@Id @GeneratedValue(strategy=GenerationType.AUTO)
	public Integer getUserId() {
		return userId;
	}

	/**
	 * Set 用户ID
	 */
	public void setUserId(Integer userId) {
		this.userId = userId;
	}

	//···后面的getXxx()、setXxx()方法省略···
}

然后在dao 包里创建IUserInfoDao.java 的接口,并继承JpaRepository<T,ID>接口:

import com.polymerize.basic.basicData.model.UserInfoModel;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * 用户信息(userInfo)dao接口
 *
 * @author: liwenqiang 2018/7/27 17:50
 **/
public interface IUserInfoDao extends JpaRepository<UserInfoModel,Integer> {
    }

3、此时已经可以启动项目进行测试,然而...启动报错了

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2018-07-30 15:51:40.428 ERROR 5652 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Cannot determine embedded database url for database type NONE

Action:

If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).

然后Google了好多资料,得知是因为数据源的配置问题,spring data jpa引入之后,会加入hibernate 的数据源配置,但是spring boot 项目如果配置的datasource 的相关信息,会去配置文件里读取,所以连个产生了问题,解决这个问题的办法有两个:

            方法一:使用注解——在启动类的@SpringApplication注解上配置 exclude = DataSourceAutoConfiguration.class

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableFeignClients
public class BasicApplication {

    public static void main(String[] args) {
        SpringApplication.run(BasicApplication.class, args);
    }
}

  但是方法一试了之后,问题并没有解决···,然后此方法放弃,试试方法二。

            方法二:自定义数据源配置:

            3.1、创建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;

import javax.sql.DataSource;

/**
 * 数据源配置
 *
 * @author: liwenqiang 2018/7/30 11:01
 **/
@Configuration
public class DataSourceConfig {

    @Bean(name = "baseDataSource")
    @Primary
    @Qualifier("baseDataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource primaryDatasource() {
        return DataSourceBuilder.create().build();
    }


}

            3.2、在创建一个jpa的配置类

/**
 * 这两个方法不适用 spring boot 2.x
 */

@Bean(name = "entityManagerFactoryPrimary")
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {

        return builder
                //设置数据源
                .dataSource(primaryDataSource)
                //设置数据源属性
                .properties(getVendorProperties(primaryDataSource))
                //设置实体类所在位置.扫描所有带有 @Entity 注解的类
                .packages("com.itguang.springbootmultidatasource.domain")
                // Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后,
                // Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作
                .persistenceUnit("primaryPersistenceUnit")
                .build();

    }

    private Map<String, String> getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }

这里要注意,由于spring boot 2.x 的变化,网上差的资料有用带参的getVendorProperties(DataSource dataSource)方法的,但是2.x 不支持,所以要用不带参的方法:

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;

/**
 * jpa配置
 *
 * @author: liwenqiang 2018/7/30 10:27
 **/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryPrimary",//配置连接工厂 entityManagerFactory
        transactionManagerRef = "transactionManagerPrimary", //配置 事物管理器  transactionManager
        basePackages = {"com.polymerize.basic.*.dao"}//设置dao(repo)所在位置
)
public class JpaConfig {

    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    @Qualifier("baseDataSource")
    private DataSource primaryDataSource;


    /**
     * @param builder
     * @return
     */
    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(primaryDataSource)
                .packages("com.polymerize.basic.*.model")
                .persistenceUnit("primaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
    }


    private Map<String, Object> getVendorProperties() {
        return jpaProperties.getHibernateProperties(new HibernateSettings());
    }


    @Primary
    @Bean(name = "entityManagerPrimary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    /**
     * 配置事物管理器
     *
     * @param builder
     * @return
     */
    @Bean(name = "transactionManagerPrimary")
    @Primary
    PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}

配置完成之后启动一下,又出现了一个问题

然后试着改了下application.properties配置文件中的配置为:spring.datasource.url 改为 spring.datasource.jdbcUrl

# MySQL数据库地址,springboot2.x需使用.jdbcUrl否则会报错
spring.datasource.jdbcUrl=jdbc:mysql://localhost:3306/polymerize

然后再启动,终于成功了!!!

github项目地址:https://github.com/little3201/polymerize

猜你喜欢

转载自blog.csdn.net/zx110503/article/details/81285727