Spring Boot+Jpa多数据源配置的完整步骤

时间:2022-10-27 15:31:27

关于

有时候,随着业务的发展,项目关联的数据来源会变得越来越复杂,使用的数据库会比较分散,这个时候就会采用多数据源的方式来获取数据。另外,多数据源也有其他好处,例如分布式数据库的读写分离,集成多种数据库等等。

下面分享我在实际项目中配置多数据源的案例。话不多说了,来一起看看详细的介绍吧

步骤

1.application.yml文件中,配置数据库源。这里primary是主库,secondary是从库。

?
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
server:
 port: 8089
 
# 多数据源配置
#primary
spring:
 primary:
 datasource:
  url: jdbc:mysql://127.0.0.1:3306/database1?autoreconnect=true&useunicode=true&characterencoding=utf-8&usessl=false&uselegacydatetimecode=false&servertimezone=asia/shanghai
  username: root
  password: ******
  driver-class-name: com.mysql.jdbc.driver
 
 #secondary
 secondary:
 datasource:
  url: jdbc:mysql://127.0.0.1:3306/database1?autoreconnect=true&useunicode=true&characterencoding=utf-8&usessl=false&uselegacydatetimecode=false&servertimezone=asia/shanghai
  username: root
  password: ******
  driver-class-name: com.mysql.jdbc.driver
 
 jpa:
 hibernate:
  primary-dialect: org.hibernate.dialect.mysql5dialect
  secondary-dialect: org.hibernate.dialect.mysql5dialect
 open-in-view: true
 show-sql: true

2.创建一个spring配置类,其中spring.primary.datasource的路径参考yml文件的配置。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@configuration
public class datasourceconfig {
 
 @bean(name = "primarydatasource")
 @qualifier("primarydatasource")
 @configurationproperties(prefix="spring.primary.datasource")
 public datasource primarydatasource() {
  return datasourcebuilder.create().build();
 }
 
 @bean(name = "secondarydatasource")
 @qualifier("secondarydatasource")
 @primary
 @configurationproperties(prefix="spring.secondary.datasource")
 public datasource secondarydatasource() {
  return datasourcebuilder.create().build();
 }
 
}

3.分别创建主库、从库的配置类。

注意:entity包和dao包的配置,以及@primary注解指定主库。

主库配置类:

?
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
@configuration
@enabletransactionmanagement
@enablejparepositories(
  entitymanagerfactoryref = "entitymanagerfactoryprimary",
  transactionmanagerref = "transactionmanagerprimary",
  basepackages = {"com.infinitus.yunxiao_data.dao.primary"}) //设置repository所在位置
public class primaryconfig {
 @autowired
 private jpaproperties jpaproperties;
 
 @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("com.infinitus.yunxiao_data.entity.primary") //设置实体类所在位置
    .persistenceunit("primarypersistenceunit")
    .build();
 }
 
 
 private map getvendorproperties(datasource datasource) {
  return jpaproperties.gethibernateproperties(datasource);
 }
 
 @primary
 @bean(name = "transactionmanagerprimary")
 public platformtransactionmanager transactionmanagerprimary(entitymanagerfactorybuilder builder) {
  return new jpatransactionmanager(entitymanagerfactoryprimary(builder).getobject());
 }
}

从库的配置类:

?
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
@configuration
@enabletransactionmanagement
@enablejparepositories(
  entitymanagerfactoryref = "entitymanagerfactorysecondary",
  transactionmanagerref = "transactionmanagersecondary",
  basepackages = {"com.infinitus.yunxiao_data.dao.secondary"}) //设置repository所在位置
public class secondaryconfig {
 @autowired
 private jpaproperties jpaproperties;
 
 @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("com.infinitus.yunxiao_data.entity.secondary") //设置实体类所在位置
    .persistenceunit("primarypersistenceunit")
    .build();
 }
 
 
 private map getvendorproperties(datasource datasource) {
  return jpaproperties.gethibernateproperties(datasource);
 }
 
 @bean(name = "transactionmanagersecondary")
 platformtransactionmanager transactionmanagersecondary(entitymanagerfactorybuilder builder) {
  return new jpatransactionmanager(entitymanagerfactorysecondary(builder).getobject());
 }
 
}

4.分别创建主、从库dao类。

主dao:

?
1
2
3
4
5
6
7
@repository
public interface primaryrepository extends jparepository<primaryentity, long> {
 
 @query(value = "select p from primaryentity p")
 list<primaryentity> querylist();
 
}

从dao:

?
1
2
3
4
5
6
7
@repository
public interface secondaryrepository extends jparepository<secondaryentity, long> {
 
 @query(value = "select p from secondaryentity p")
 list<secondaryentity> querylist();
 
}

5.分别创建主、从库entity类。

主entity:

?
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
50
51
52
53
54
55
@entity
@table(name = "holiday_scheme")
@entitylisteners(auditingentitylistener.class)
public class primaryentity extends abstractpersistable<long> {
 @column(name = "date")
 public string date;
 @column(name = "hour")
 public string hour;
 @column(name = "holiday")
 public string holiday;
 @column(name = "holiday_explain")
 public string holiday_explain;
 
 public string getdate() {
  return date;
 }
 
 public void setdate(string date) {
  this.date = date;
 }
 
 public string gethour() {
  return hour;
 }
 
 public void sethour(string hour) {
  this.hour = hour;
 }
 
 public string getholiday() {
  return holiday;
 }
 
 public void setholiday(string holiday) {
  this.holiday = holiday;
 }
 
 public string getholiday_explain() {
  return holiday_explain;
 }
 
 public void setholiday_explain(string holiday_explain) {
  this.holiday_explain = holiday_explain;
 }
 
 @override
 public string tostring() {
  return "primaryentity{" +
    "date='" + date + '\'' +
    ", hour='" + hour + '\'' +
    ", holiday='" + holiday + '\'' +
    ", holiday_explain='" + holiday_explain + '\'' +
    '}';
 }
}

从entity:

?
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
@entity
@table(name = "active_dashboards")
@entitylisteners(auditingentitylistener.class)
public class secondaryentity extends abstractpersistable<long> {
 
 @column(name = "dashboard_id")
 public string dashboard_id;
 @column(name = "user_id")
 public string user_id;
 @column(name = "order_index")
 public string order_index;
 
 public string getdashboard_id() {
  return dashboard_id;
 }
 
 public void setdashboard_id(string dashboard_id) {
  this.dashboard_id = dashboard_id;
 }
 
 public string getuser_id() {
  return user_id;
 }
 
 public void setuser_id(string user_id) {
  this.user_id = user_id;
 }
 
 public string getorder_index() {
  return order_index;
 }
 
 public void setorder_index(string order_index) {
  this.order_index = order_index;
 }
 
 @override
 public string tostring() {
  return "secondaryentity{" +
    "dashboard_id='" + dashboard_id + '\'' +
    ", user_id='" + user_id + '\'' +
    ", order_index='" + order_index + '\'' +
    '}';
 }
}

6.controller请求获取不同数据库的数据。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@restcontroller
@requestmapping("/database")
public class mailcontroller {
 private final logger logger = loggerfactory.getlogger(this.getclass());
 
 @autowired
 primaryrepository primaryrepository;
 @autowired
 secondaryrepository secondaryrepository;
 
 @requestmapping("/primary")
 @responsebody
 public string primary() {
  return primaryrepository.querylist().tostring();
 }
 
 @requestmapping("/secondary")
 @responsebody
 public string secondary() {
  return secondaryrepository.querylist().tostring();
 }
 
}

注意

下面提两个在配置多数据源时遇到的坑点,一不注意就掉坑了。

1.application类不需要配置@enablejparepositories注解,会报如下错误。

a component required a bean named 'entitymanagerfactory' that could not be f

2.注意检查dao类,获取数据的方法上格式是否正确,有没有某个字段是表中不存在的,避免启动异常。如下,secondaryentity表中是不存在job_name字段的,所以注释掉才能启动成功等。

?
1
2
//@query(value = "select p from secondaryentity p where p.job_name = ?1")
//list<secondaryentity> queryodcrecord(string job_name);

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。

原文链接:https://huangweicai.github.io/2019/01/08/SpringBoot+Jpa多数据源配置/