Springboot下通过Jpa连接MySQL数据库实现ORM对象关系映射

Springboot下通过Jpa连接MySQL数据库实现ORM对象关系映射

Springboot下通过Jpa连接MySQL数据库实现ORM对象关系映射

1.1 依赖的搭建

要在Springboot中使用Jpa首先要引入项目依赖,这里以Maven为例:

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>

1.2 配置数据源

等到Maven Sync完成后,我们需要在application.properties文件中配置数据源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 注释: 在jdbc的url中,需要注意: 
# 编码设置为utf-8
# 时区需要手动指定,否则在使用系统自动管理的Timestamp时会出现时间与北京时间相差11小时左右
spring.datasource.url=jdbc:mysql://数据库IP:端口/数据库名称?charset=utf8mb4&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=你的用户名
spring.datasource.password=你的密码
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 在Springboot版本>=2.0,请根据需要将数据库引擎切换为InnoDB
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
# 是否在控制台输出sql语句
spring.jpa.show-sql=true
# 自动生成ddl语句
# 这里需要解释一下常用参数:
# create: 每次加载Hibernate时删除数据库中所有的数据和表,再重新创建新的(慎用!)
# update: 当表不存在时自动创建数据表,当表存在时自动根据model更新表的结构,表中的数据保持不变。(常用)
# (注意:当model中的字段被删除时,update模式是不会删除字段的)
# validate: 每次加载Hibernate时比对表的结构,根据model自动做出修改,!但是新的表不会被创建!
spring.jpa.hibernate.ddl-auto=update

1.3 开始使用

在开始使用之前,如果你使用的是IntelliJ IDEA,那么我可能要跟你唠嗑一下它的数据源机制。

在你还未配置Data Source前,写DO类,会出现Table画横线报错的情况,如图所示

报错信息

这个错还不是警告,直接画红标出,看着贼难受。所以,这时候需要配置一个数据源。在最右侧的侧边栏点击Database->加号->Data Source->MySQL,然后根据提示填写信息,完成后同步一下就ok了

数据源配置

唠嗑结束,回到正题

1.3.1 数据实体类的创建

首先,需要创建数据实体类。这里以User表的实体类为例: (UsersDO.java)

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.yeliheng.test.domain;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "users")
public class UsersDO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
private String nickname;
@Column
private String phone;
@Column
private String password;
@CreationTimestamp
private LocalDateTime createDateTime;
@UpdateTimestamp
private LocalDateTime updateDateTime;

public String getNickname() {
return nickname;
}

public void setNickname(String nickname) {
this.nickname = nickname;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public LocalDateTime getCreateDateTime() {
return createDateTime;
}

public void setCreateDateTime(LocalDateTime createDateTime) {
this.createDateTime = createDateTime;
}

public LocalDateTime getUpdateDateTime() {
return updateDateTime;
}

public void setUpdateDateTime(LocalDateTime updateDateTime) {
this.updateDateTime = updateDateTime;
}

public long getId() {
return id;
}

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

这里对以上代码的关键点进行解释:

@Entity 注解:用于数据库的实体类均需要加上Entity注解

@Table 注解:顾名思义,这是一个表注解,可在name属性中赋值需要的表名。默认表名与类名相同

@Id : 表示主键ID,如果想让id自增则需要再加上@GeneratedValue(strategy = GenerationType.IDENTITY)注解

@Column 注解:表示这是一个字段

这里,我们希望将数据的创建时间与更新时间交给框架来管理,则我们需要加上@CreationTimestamp@UpdateTimestamp注解。并将数据类型定义为LocalDateTime

这样有什么好处?首先,我们无需在数据更新时自行去实现时间更新的逻辑,用户的注册时间以及更改时间完全交付给系统管理,提供很大的便利。其次,我们无需自行格式化时间戳,因为Jpa的时间戳与MySQL的时间戳有格式上的不同,在格式化的过程中,极其容易踩坑。

1.3.2 开始与数据库进行交互(Dao层的创建)

首先解释一下什么叫DAO层

DAO即Data Access Object,能够实现对数据持久化的访问。不止是数据库,持久化的数据例如文件的操作,都可在DAO层进行。也算是一种规范。简单地说,DAO层用于隔离业务逻辑代码和数据访问代码,隔离不同数据的实现。多说无用,直接开始增删改查。

Jpa已经帮忙封装完Dao层的相关代码,所以,我们实现增删改查十分容易。只需要定义一个接口,这个接口继承自org.springframework.data.repository.Repository<T, ID> 接口,一句话即可完成初始化。T表示数据的实体类,例如我们的UsersDO类,ID表示实体类的主键类型。最后,别忘了加上@Respository这个注解,这个注解用于表示存储层Bean。代码如下:

1
2
3
4
5
6
7
8
9
10
11
package com.yeliheng.test.dao;

import com.yeliheng.test.domain.UsersDO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UsersDao extends JpaRepository<UsersDO,Long> {
Boolean existsByPhone(String phone);
UsersDO findByPhone(String phone);
}

我们在定义完接口后,在接口中实现了两个方法:顾名思义,一个是通过手机号判断用户是否存在,一个是通过手机号查找用户。

就这么简单,Jpa就可以实现查询功能。

稍微提一下方法名称:

findByXXX:XXX表示你要查什么字段。你甚至可以findByXXXAndXXXAndXXXAndXXX……多少字段都没问题,中间用And进行连接。超级方便。

exists同理。

这里仅仅列举了两种操作,Jpa的接口功能十分强大, 可自行定制使用其他功能,例如排序、分页、多表联查等等等等…用户自行查表获取。

1.3.3 在service里调用

通俗易懂,直接上代码。

1
2
3
4
5
6
7
8
@Autowired
private UsersDao usersDao;
public void addUser(){
UsersDO usersDO = new UsersDO();
usersDO.setPhone("11111111111");
usersDO.setPassword("h3khj1¥sdjs%#0x/!%$#dsjd!a!/1#@!");
usersDao.save(usersDO);
}

1
2
3
4
5
6
@Autowired
private UsersDao usersDao;
public void deleteUser(){
UsersDO usersDO = usersDao.findByPhone("1111111111");
usersDao.delete(usersDO);
}

与增的方法相同,就是多一步查找出UsersDO的实例,再调用set方法进行设置,最后save即可。

1
2
3
4
5
6
7
@Autowired
private UsersDao usersDao;
public void updateUser(){
UUsersDO usersDO = usersDao.findByPhone("1111111111");
usersDO.setPhone("12222222222");
usersDao.save(usersDO);
}

1
2
3
4
5
@Autowired
private UsersDao usersDao;
public void queryUser(){
UsersDO usersDO = usersDao.findByPhone("1111111111");
}

预告

下一篇,我将讲讲我在Filter过滤器中使用Dao层踩的坑。