Spring Boot整合Jpa多數據源

Spring Boot整合Jpa多數據源

本文是Spring Boot整合數據持久化方案的最後一篇,主要和大夥來聊聊Spring Boot整合Jpa多數據源問題。在Spring Boot整合JbdcTemplate多數據源、Spring Boot整合MyBatis多數據源以及Spring Boot整合Jpa多數據源這三個知識點中,整合Jpa多數據源算是最複雜的一種,也是不少人在配置時最容易出錯的一種。java

工程建立

首先是建立一個Spring Boot工程,建立時添加基本的Web、Jpa以及MySQL依賴,以下:mysql

img

建立完成後,添加Druid依賴,這裏和前文的要求同樣,要使用專爲Spring Boot打造的Druid,大夥可能發現了,若是整合多數據源必定要使用這個依賴,由於這個依賴中才有DruidDataSourceBuilder。完整依賴以下:web

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

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

如此以後,工程就建立成功了。spring

基本配置

在基本配置中,咱們首先來配置多數據源基本信息以及DataSource,首先在application.properties中添加以下配置信息:sql

spring.datasource.one.url=jdbc:mysql:///ssm?serverTimezone=UTC
spring.datasource.one.username=xiaoliu
spring.datasource.one.password=960614abcd
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource

spring.datasource.two.url=jdbc:mysql:///xiaoliu?serverTimezone=UTC
spring.datasource.two.username=xiaoliu
spring.datasource.two.password=960614abcd
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource

spring.jpa.properties.hibernate.ddl-auto=update
spring.jpa.properties.database-platform=mysql
spring.jpa.properties.database=mysql
spring.jpa.properties.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

這裏Jpa的配置和上文相比key中多了properties,多數據源的配置和前文一致,而後接下來配置兩個DataSource,以下:app

@Configuration
public class DataSourceConfig {
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.one")
    DataSource dsOne(){
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.two")
    DataSource dsTwo(){
        return DruidDataSourceBuilder.create().build();
    }
}

這裏的配置和前文的多數據源配置基本一致,可是注意多了一個在Spring中使用較少的註解@Primary,這個註解必定不能少,不然在項目啓動時會出錯,@Primary表示當某一個類存在多個實例時,優先使用哪一個實例。ide

好了,這樣,DataSource就有了。spring-boot

多數據源配置

接下來配置Jpa的基本信息,這裏兩個數據源,我分別在兩個類中來配置,先來看第一個配置:測試

@Configuration
@EnableJpaRepositories(basePackages = "cn.itxiaoliu.dao1",entityManagerFactoryRef ="localContainerEntityManagerFactoryBean1",
transactionManagerRef = "platformTransactionManager1")
public class JpaConfig1 {
    @Autowired
    @Qualifier("dsOne")
    DataSource dsOne;
    /** * */
    @Autowired
    JpaProperties jpaProperties;
    @Bean
    @Primary
    LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean1(EntityManagerFactoryBuilder builder){
        return builder.dataSource(dsOne)
                .properties(jpaProperties.getProperties())
                .persistenceUnit("pu1")
                .packages("cn.itxiaoliu.bean")
                .build();
    }
    @Bean
    PlatformTransactionManager platformTransactionManager1(EntityManagerFactoryBuilder builder){
        return new JpaTransactionManager(localContainerEntityManagerFactoryBean1(builder).getObject());
    }
}

首先這裏注入dsOne,再注入JpaProperties,JpaProperties是系統提供的一個實例,裏邊的數據就是咱們在application.properties中配置的jpa相關的配置。而後咱們提供兩個Bean,分別是LocalContainerEntityManagerFactoryBean和PlatformTransactionManager事務管理器,不一樣於MyBatis和JdbcTemplate,在Jpa中,事務必定要配置。在提供LocalContainerEntityManagerFactoryBean的時候,須要指定packages,這裏的packages指定的包就是這個數據源對應的實體類所在的位置,另外在這裏配置類上經過@EnableJpaRepositories註解指定dao所在的位置,以及LocalContainerEntityManagerFactoryBean和PlatformTransactionManager分別對應的引用的名字。ui

好了,這樣第一個就配置好了,第二個基本和這個相似,主要有幾個不一樣點:

  • dao的位置不一樣
  • persistenceUnit不一樣
  • 相關bean的名稱不一樣

注意實體類能夠共用。

代碼以下:

@Configuration
@EnableJpaRepositories(basePackages = "cn.itxiaoliu.dao2",entityManagerFactoryRef ="localContainerEntityManagerFactoryBean2",
transactionManagerRef = "platformTransactionManager2")
public class JpaConfig2 {
    @Autowired
    @Qualifier("dsTwo")
    DataSource dsTwo;
    /** * */
    @Autowired
    JpaProperties jpaProperties;
    @Bean
    LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean2(EntityManagerFactoryBuilder builder){
        return builder.dataSource(dsTwo)
                .properties(jpaProperties.getProperties())
                .persistenceUnit("pu2")
                .packages("cn.itxiaoliu.bean")
                .build();
    }
    @Bean
    PlatformTransactionManager platformTransactionManager2(EntityManagerFactoryBuilder builder){
        return new JpaTransactionManager(localContainerEntityManagerFactoryBean2(builder).getObject());
    }
}

接下來,在對應位置分別提供相關的實體類和dao便可,數據源一的dao以下:

public interface BookDao1 extends JpaRepository<Book,Integer> {
}

數據源二的dao以下:

public interface BookDao2 extends JpaRepository<Book,Integer> {
}

共同的實體類以下:

@Entity(name = "t_book")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private String author;

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

到此,全部的配置就算完成了,接下來就能夠在Service中注入不一樣的UserDao,不一樣的UserDao操做不一樣的數據源。

其實整合Jpa多數據源也不算難,就是有幾個細節問題,這些細節問題解決,其實前面介紹的其餘多數據源整個都差很少。

接下來在測試類中進行測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class Jpa2ApplicationTests {

    @Autowired
    BookDao1 bookDao1;
    @Autowired
    BookDao2 bookDao2;

    @Test
    public void contextLoads() {
        List<Book> all = bookDao1.findAll();
        System.out.println(all);
        List<Book> all1 = bookDao2.findAll();
        System.out.println(all1);
    }

}
相關文章
相關標籤/搜索