spring+Jpa多数据源配置的方法示例

时间:2022-10-20 15:43:24

今天临下班时遇到了一个需求,我的管理平台需要从不同的数据库中获取数据信息,这就需要进行spring多数据源配置,对于这种配置,第一次永远都是痛苦的,不过经历了这次的折磨,今后肯定会对这种配置印象深刻。我们这里简单回顾一下流程。

我们配置了两个数据库,一个是公司的数据库,另一个是我本地的一个数据库。首先是application.yml的配置(其中对于公司的数据库我们采取了假的地址,而本机的数据库是真是存在对应的表和库的)

数据库信息:

spring+Jpa多数据源配置的方法示例

数据表信息:

spring+Jpa多数据源配置的方法示例

1、application.yml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
datasource:
 primary:
  url: jdbc:mysql://companyurl.com:5002/db1
  username: unameq
  password: passwd1
  driver-class-name: com.mysql.jdbc.driver
 secondary:
  url: jdbc:mysql://localhost:3306/django_test
  username: root
  password: 123456
  driver-class-name: com.mysql.jdbc.driver
 jpa:
 database-platform: org.hibernate.dialect.mysql5dialect
 hibernate:
  ddl-auto: update
  show-sql: true

2、创建总的datasource配置文件以及两个repostory的配置文件primaryconfig以及secondaryconfig

datasourceconfig

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@configuration
public class datasourceconfig {
 @bean(name = "primarydatasource")
 @qualifier("primarydatasource")
 @configurationproperties(prefix="spring.datasource.primary")//对应的数据库配置信息
 public datasource primarydatasource() {
  return datasourcebuilder.create().build();
 }
 
 @bean(name = "secondarydatasource")
 @qualifier("secondarydatasource")
 @primary
 @configurationproperties(prefix="spring.datasource.secondary")
 public datasource secondarydatasource() {
  return datasourcebuilder.create().build();
 }
}

primaryconfig

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@configuration
@enabletransactionmanagement
@enablejparepositories(
  entitymanagerfactoryref="entitymanagerfactoryprimary",
  transactionmanagerref="transactionmanagerprimary",
  basepackages= { "数据访问层所在的包" }) //设置repository所在位置
public class primaryconfig {
 
 @autowired @qualifier("primarydatasource")
 private datasource primarydatasource;
 
 @primary
 @bean(name = "entitymanagerprimary")
 public entitymanager entitymanager(entitymanagerfactorybuilder builder) {
  return entitymanagerfactoryprimary(builder).getobject().createentitymanager();
 }
 
 @primary
 @bean(name = "entitymanagerfactoryprimary")
 public localcontainerentitymanagerfactorybean entitymanagerfactoryprimary (entitymanagerfactorybuilder builder) {
  return builder
    .datasource(primarydatasource)
    .properties(getvendorproperties(primarydatasource))
    .packages("实体类所在的包") //设置实体类所在位置
    .persistenceunit("primarypersistenceunit")
    .build();
 }
 
 @autowired
 private jpaproperties jpaproperties;
 
 private map<string, string> getvendorproperties(datasource datasource) {
  return jpaproperties.gethibernateproperties(datasource);
 }
 
 @primary
 @bean(name = "transactionmanagerprimary")
 public platformtransactionmanager transactionmanagerprimary(entitymanagerfactorybuilder builder) {
  return new jpatransactionmanager(entitymanagerfactoryprimary(builder).getobject());
 }
}

secondaryconfig

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@configuration
@enabletransactionmanagement
@enablejparepositories(
  entitymanagerfactoryref="entitymanagerfactorysecondary",
  transactionmanagerref="transactionmanagersecondary",
  basepackages= { "数据访问层所在的包" }) //设置repository所在位置
public class secondaryconfig {
 
 @autowired
 @qualifier("secondarydatasource")
 private datasource secondarydatasource;
 
 @bean(name = "entitymanagersecondary")
 public entitymanager entitymanager(entitymanagerfactorybuilder builder) {
  return entitymanagerfactorysecondary(builder).getobject().createentitymanager();
 }
 
 @bean(name = "entitymanagerfactorysecondary")
 public localcontainerentitymanagerfactorybean entitymanagerfactorysecondary(entitymanagerfactorybuilder builder) {
  return builder
    .datasource(secondarydatasource)
    .properties(getvendorproperties(secondarydatasource))
    .packages("实体类所在的包") //设置实体类所在位置
    .persistenceunit("secondarypersistenceunit")
    .build();
 }
 
 @autowired
 private jpaproperties jpaproperties;
 
 private map<string, string> getvendorproperties(datasource datasource) {
  return jpaproperties.gethibernateproperties(datasource);
 }
 
 @bean(name = "transactionmanagersecondary")
 platformtransactionmanager transactionmanagersecondary(entitymanagerfactorybuilder builder) {
  return new jpatransactionmanager(entitymanagerfactorysecondary(builder).getobject());
 }
}

3、然后我对于本地数据库新建实体类peopleperson

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@entity
@table(name = "people_person")
public class peopleperson implements serializable {
 @id
 @generatedvalue
 private integer id;
 
 @column(name = "name")
 private string name;
 
 @column(name = "age")
 private integer age;
 
 public peopleperson() {
 }
 
 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 integer getage() {
  return age;
 }
 
 public void setage(integer age) {
  this.age = age;
 }
 
 @override
 public string tostring() {
  return "peopleperson{" +
    "id=" + id +
    ", name='" + name + '\'' +
    ", age=" + age +
    '}';
 }
}

并创建对应的repositoy,peoplepersondao并创建了一个findall的方法

?
1
2
3
4
@transactional@repositorypublic interface peoplepersondao extends jparepository<peopleperson, long>
 {
   list<peopleperson> findall();
 }

4、最后,在test包中进行测试

?
1
2
3
4
5
6
7
8
9
@autowired
private peoplepersondao peoplepersondao;
@test
public void testmultidatasource() {
 list<peopleperson> list = peoplepersondao.findall();
 for (int i = 0; i < list.size(); i++) {
  logger.info(list.get(i).tostring());
 }
}

测试结果

spring+Jpa多数据源配置的方法示例

 一些坑

不仅仅是dao层扫描的包需要区分,对于实体类所在的包,不同的datasource的配置中也需要区分开

对于这种套路性的东西,总结一遍是非常必要的,下次可以节省许多不必要的时间,对于内部原理,我将在完成对ioc和aop分析后反过来分析其原理。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://bryantchang.github.io/2018/07/31/spring-multidatasource/