1. 程式人生 > >SpringBoot2.0 jpa多資料來源配置

SpringBoot2.0 jpa多資料來源配置

隨著Springboot升級到2.0,原來1.5.x的Jpa多資料來源配置不能用了。現在總結一下Springboot2.0的jpa多資料來源配置

連線池還是用druid,但是不能用druid的starter了,譬如在1.5.x時用的是

<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>1.1.6</version>
		</dependency>
升級到2.0後,再用這個就會報錯,因為一個AutoConfig的類缺失。那麼要使用druid需要用下面的配置
<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.6</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
注意log4j是druid強依賴的不能少,web是因為druid有web介面可以訪問,也不能少。

application.yml也有變化

原來是這樣的

spring:
  jpa:
    database: mysql
    show-sql: true
    hibernate:
      ddl-auto: update
      naming:
        strategy: org.hibernate.cfg.ImprovedNamingStrategy #命名策略,加分隔線"_"
主要變化就是naming這裡,原來的ImprovedNamingStrategy不讓用了,改成了下面的類
spring:
  datasource:
    primary:
      url: jdbc:mysql://localhost:3306/company?autoReconnect=true&useUnicode=true
      username: root
      password: root
    secondary:
      url: jdbc:mysql://localhost:3306/com1?autoReconnect=true&useUnicode=true
      username: root
      password: root
  jpa:
    database: mysql
    generate-ddl: true
    show-sql: true
    hibernate:
      ddl-auto: update
      naming:
        physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy


雙資料來源:

先來配置druid的DataSource,這個類在新老版本里都能用,不需要變化。

package com.example.demo.druid;

import com.alibaba.druid.pool.DruidDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.sql.SQLException;

/**
 * @author wuweifeng wrote on 2017/10/23.
 * 資料庫連線屬性配置
 */
@ServletComponentScan
@Configuration
public class DruidDBConfig {
    private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class);

    @Value("${spring.datasource.primary.url}")
    private String dbUrl1;

    @Value("${spring.datasource.primary.username}")
    private String username1;

    @Value("${spring.datasource.primary.password}")
    private String password1;

    @Value("${spring.datasource.secondary.username}")
    private String username2;

    @Value("${spring.datasource.secondary.password}")
    private String password2;

    @Value("${spring.datasource.secondary.url}")
    private String dbUrl2;

    @Value("com.mysql.jdbc.Driver")
    private String driverClassName;

    @Value("5")
    private int initialSize;

    @Value("5")
    private int minIdle;

    @Value("20")
    private int maxActive;

    @Value("60000")
    private int maxWait;

    /**
     * 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
     */
    @Value("60000")
    private int timeBetweenEvictionRunsMillis;
    /**
     * 配置一個連線在池中最小生存的時間,單位是毫秒
     */
    @Value("300000")
    private int minEvictableIdleTimeMillis;

    @Value("SELECT 1 FROM DUAL")
    private String validationQuery;

    @Value("true")
    private boolean testWhileIdle;

    @Value("false")
    private boolean testOnBorrow;

    @Value("false")
    private boolean testOnReturn;

    /**
     * 開啟PSCache,並且指定每個連線上PSCache的大小
     */
    @Value("true")
    private boolean poolPreparedStatements;

    @Value("20")
    private int maxPoolPreparedStatementPerConnectionSize;
    /**
     * 配置監控統計攔截的filters,去掉後監控介面sql無法統計,'wall'用於防火牆
     */
    @Value("stat,wall,log4j")
    private String filters;
    /**
     * 通過connectProperties屬性來開啟mergeSql功能;慢SQL記錄
     */
    @Value("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500")
    private String connectionProperties;

    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    public DataSource dataSource() {
        return getDruidDataSource(username1, password1, dbUrl1);
    }

    @Bean(name = "secondaryDataSource")
    @Qualifier("secondaryDataSource")
    @Primary
    public DataSource secondaryDataSource() {
        return getDruidDataSource(username2, password2, dbUrl2);
    }

    private DruidDataSource getDruidDataSource(String username, String password, String url) {
        DruidDataSource datasource = new DruidDataSource();

        datasource.setUrl(url);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);

        //configuration
        datasource.setInitialSize(initialSize);
        datasource.setMinIdle(minIdle);
        datasource.setMaxActive(maxActive);
        datasource.setMaxWait(maxWait);
        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        datasource.setValidationQuery(validationQuery);
        datasource.setTestWhileIdle(testWhileIdle);
        datasource.setTestOnBorrow(testOnBorrow);
        datasource.setTestOnReturn(testOnReturn);
        datasource.setPoolPreparedStatements(poolPreparedStatements);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        try {
            datasource.setFilters(filters);
        } catch (SQLException e) {
            logger.error("druid configuration initialization filter : {0}", e);
        }
        datasource.setConnectionProperties(connectionProperties);

        return datasource;
    }
}

第一資料來源:

package com.example.demo.druid;

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;

/**
 * @author wuweifeng wrote on 2017/10/31.
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryPrimary",
        transactionManagerRef = "transactionManagerPrimary",
        basePackages = {"com.example.demo.repository.primary"})
public class PrimaryConfig {

    @Resource
    @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;

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

    @Resource
    private JpaProperties jpaProperties;

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

    /**
     * 設定實體類所在位置
     */
    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(primaryDataSource)
                .packages("com.example.demo.model.primary")
                .persistenceUnit("primaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
    }

    @Primary
    @Bean(name = "transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }

}
第二資料來源:
package com.example.demo.druid;

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;

/**
 * @author by wuweifeng on 2017/10/10.
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactorySecondary",
        transactionManagerRef = "transactionManagerSecondary",
        basePackages = {"com.example.demo.repository.secondary"})
public class SecondaryConfig {

    @Resource
    @Qualifier("secondaryDataSource")
    private DataSource secondaryDataSource;

    @Bean(name = "entityManagerSecondary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    }

    @Resource
    private JpaProperties jpaProperties;

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

    @Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(secondaryDataSource)
                .packages("com.example.demo.model.secondary")
                .persistenceUnit("secondaryPersistenceUnit")
                .properties(getVendorProperties())
                .build();
    }

    @Bean(name = "transactionManagerSecondary")
    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
    }

}

注意把裡面的model包名和Repository包名替換為你自己的即可。

它與1.5.x版本的主要區別在於getVerdorProperties這個方法,原來的getHibernateProperties是傳引數DataSource,現在是傳引數HibernateSettings,

HibernateSettings類其實就是配置列名生成策略的,我們已經在yml裡配置過了,這裡直接new 一個空類過去就行了。

這樣我們就完成了Springboot 2.0.0.M7的多資料來源Jpa配置了。

還有一個地方需要提一下,Springboot2.0依賴了Hibernate5.2版本,1.5.x依賴的是Hibernate5.0.12版本,這兩個版本在處理Id自增方面是不一樣的。

在老版本里,我們定義了

 @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    public Long getId() {
        return id;
    }
Id生成策略為Auto,那麼預設會被轉出Id自增。

在新版本里,Auto是不行的,不會自增,而且Hibernate會額外創建出來一個表來專門維護Id。可以自行嘗試一下,會多出來一個表。

我們如果需要自增的Id,需要顯式指定

@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public Long getId() {
        return id;
    }


相關推薦

SpringBoot2.0 jpa資料來源配置

隨著Springboot升級到2.0,原來1.5.x的Jpa多資料來源配置不能用了。現在總結一下Springboot2.0的jpa多資料來源配置連線池還是用druid,但是不能用druid的starter了,譬如在1.5.x時用的是<dependency>

springboot2.0.5+jpa資料來源配置

1.首先配置資料來源連線總裝類DataSourcesConfig package com.cpic.dataSources; import org.springframework.beans.factory.annotation.Qualifier; import org.springfr

Spring Boot Jpa資料來源配置

前言隨著業務量發展,我們通常會進行資料庫拆分或是引入其他資料庫,從而我們需要配置多個數據源,如:user一個庫,business一個庫。那麼接下來我們就要考慮怎麼去在spring boot中實現多個數據源的配置。 ××× 實現建表首先是建表語句,我們要建立兩個資料庫,並各庫內新建一張表user表mysql

SpringBoot2.0資料來源

1、多資料來源的應用場景:大型網際網路公司(商城) 垂直拆分:根據業務劃分具體資料庫 在一個專案中有多個數據源(不同庫的jdbc連線)(個數無限制,具體個數看記憶體) 多資料來源如何劃分:分包(根據業務劃分,類似於jar包),註解方式 2、多資料整合(分包整合) @

springBoot+Hibernate(Jpa)資料來源配置與使用

在學習的過程中,大多時候專案與資料庫都在本機上,使用hibernate或者mybatits加上簡單的配置就能夠打通程式到資料庫路徑,讓程式能夠訪問到資料庫。然而在一些情況下,我們不僅需要訪問本機的資料庫,還需要訪問到另外一個數據庫中的資源。本文書寫的目的便在於解

sping4 + jpa 資料來源配置, 多種實現

persistence-mysql.xml   及   orm-mysql.xml 的配置請參考我另外博文中 xml配置    ( 這裡是最簡單的配置方式,    後面的文章中有更智慧的配置方式)          搞外包,他們公司用到jpa,可是沒有一個人會. 真的是

SpringBoot2.0 jpa Druid log4jdbc 資料來源 讀寫分離

最近搭建框架玩,想搭建一個讀寫分離的東東,查閱了一天的資料,總算是弄出來了現在把程式碼分享出來,希望能幫到大家 第一步 配置檔案 spring: thymeleaf: prefix: classpath:/templates/ suff

SpringBoot2.0之八 資料來源配置

  在開發的過程中我們可能都會遇到對接公司其他系統等需求,對於外部的系統可以採用介面對接的方式,對於一個公司開發的兩個系統,並且知道相關資料庫結構的情況下,就可以考慮使用多資料來源來解決這個問題。SpringBoot為我們提供了相對簡單的實現。 一、建立如下結

Spring Boot的Spring-data-jpa資料來源配置實戰

一 新建pom <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>

基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 資料來源配置

Github 地址:github.com/Snailclimb/…(SpringBoot和其他常用技術的整合,可能是你遇到的講解最詳細的學習案例,力爭新手也能看懂並且能夠在看完之後獨立實踐。基於最新的 SpringBoot2.0+,是你學習SpringBoot 的最佳指南。) ,歡迎各位 Star。

新手也能看懂,基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 資料來源配置

Github 地址:https://github.com/Snailclimb/springboot-integration-examples(SpringBoot和其他常用技術的整合,可能是你遇到的講解最詳細的學習案例,力爭新手也能看懂並且能夠在看完之後獨立實踐。基於最新的 S

springboot v2.0.3版本資料來源配置

本篇分享的是springboot多資料來源配置,在從springboot v1.5版本升級到v2.0.3時,發現之前寫的多資料來源的方式不可用了,捕獲錯誤資訊如: 異常:jdbcUrl is required with driverClassName. 先來說下之前的多資料來源配置如: 1

springboot+jpa 實現不同資料庫的資料來源配置

廢話不多說,直接看配置! 1、application.yml # 多資料來源配置 #primary spring: primary: datasource: url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/dico_d

Spring Boot資料來源配置(一)durid、mysql、jpa整合

目前在做一個統計專案。需要多資料來源整合,其中包括mysql和mongo。本節先講mysql、durid、jpa與spring-boot的整合。 引入Durid包 <dependency> <groupId>com.a

Srping + JPA + Hibernate 資料來源配置

專案中有配置多資料來源的需求,查了一些資料最終實現,主要參考資料: http://www.cnblogs.com/linjiqin/archive/2011/02/12/1952904.html https://my.oschina.net/frankly/blog/277

Springboot 2.1.5 配置JPA資料來源

最近在學springboot,照著網上部落格想試著配一下Jpa的多資料來源,但發現因為springboot版本太高的問題,網上的d

Spring Boot 2.x基礎教程:Spring Data JPA資料來源配置

[上一篇](http://blog.didispace.com/spring-boot-learning-21-3-7/)我們介紹了在使用JdbcTemplate來做資料訪問時候的多資料來源配置實現。接下來我們繼續學習如何在使用Spring Data JPA的時候,完成多資料來源的配置和使用。 ## 新增多

spring boot的Jdbc資料來源配置實戰

一 新建依賴 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sprin

一次資料來源 配置問題記錄

  現在的專案是個多資料來源的配置,前兩天 做專案遷移,要把另一個專案遷移到api的專案裡面。於是 貼上複製後,發現不能執行。。。 最後發現是多資料來源配置出了問題。      <?xml version="1.0" encoding="UTF-8"?

Spring Boot2.0資料來源分散式事務問題

分散式事務解決方案的問題, 分散式事務產生的原因:   多個不同的服務連線不同的資料來源 ,做分散式事務的管理。   這種情況是連線兩個資料來源的情況,然後事務管理器是這樣的 只管理了test02的這端業務程式碼。所以test02的這個會回滾! 但是test01會入庫哦 這屬於