6.1、本节目标:
- JPA 简介
- Spring Data JPA 用法介绍
- Spring Data JPA、Hibernate/Mybatis/Mybatis-plus 与 Spring Boot 集成
- 数据持久化实战
6.2、JPA 简介
6.2.1、什么是JPA?
-
JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述
对象-关系表
的映射关系,并将运行期的实体对象持久化到数据库中。 -
实现: 支持 JPA 2.2 版本的框架
- DataNucleus (from version 5.1)
- EclipseLink (from version 2.7)
- Hibernate (from version 5.3)
- OpenJPA (from version 3.0)
6.2.2、JPA 核心概念
-
实体
- 实体表示关系数据库中的表
- 每个实体实例对应于该表中的行
- 类必须用 javax.persistence.Entity 注解
- 类必须有一个
public
或protected
的无参构造函数 - 实体实例被当做值以分离对象方式进行传递(例如通过会话bean的远程业务接口),则该类必须实现
Serializable
接口 - 唯一的对象识别符:简单主键(
javax.persistence.idjavax.persistence.Id
)、复合主键(javax.persistence.EmbeddedId
和javax.persistence.IdClass
)
-
关系
- 一对一:@OneToOne
- 一对多:@OneToMany
- 多对一:@ManyToOne
- 多对多:@ManyToMany
6.2.3、EntityManager
EntityManager接口:
- 定义用于与持久性上下文进项交互的方法
- 创建和删除持久实体实例,通过实体的主键查找实体
- 允许在实体上运行查询
获取 EntityManager 实例:
EntityManagerFactory emf=Persistence.createEntityManagerFactory("Student_details");
查找实体:
EntityManagerFactory emf=Persistence.createEntityManagerFactory("Student_details");
EntityManager em=emf.createEntityManager();
StudentEntity s=em.find(StudentEntity.class,101);
6.3、Spring Data JPA
6.3.1、什么是 Spring Data JPA?
- 是较大的 Spring Data 家族的一部分
- 对基于 JPA 的数据访问层的增强支持
- 使得构建使用数据访问技术的 spring 驱动的应用程序更加容易
- 官方文档
6.3.2、常用接口
CrudRepository:
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S var1);
<S extends T> Iterable<S> saveAll(Iterable<S> var1);
Optional<T> findById(ID var1);
boolean existsById(ID var1);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> var1);
long count();
void deleteById(ID var1);
void delete(T var1);
void deleteAll(Iterable<? extends T> var1);
void deleteAll();
}
PagingAndSortingRepository
用来分页:
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort var1);
Page<T> findAll(Pageable var1);
}
自定义查询:
根据方法名创建查询,继承Repository
6.4、Spring Data JPA、Hibernate 与 Spring Boot 集成
环境准备
- Mysql 8
- Spring Data JPA
- Hibernate
- Mysql Connector/J
新建一个 jpa-in-action
的项目,将上一节中thymeleaf-in-action
中的内容拷贝过来。
修改pom文件,添加相关依赖:
<!-- spring-boot-starter-data-jpa依赖,可以省略版本,Spring Boot中已已自动帮我们定义依赖版本 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- 内存数据库,只在运行时使用,因为目前还没有使用mysql数据库,引入了mysql的依赖之后启动会报错,所以先引入h2内存数据库-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
<scope>runtime</scope>
</dependency>
注意:
上面引入了H2内存数据库,在运行时使用,如果不引入,因为我们目前还没有指定数据源,但是又引入了mysql的依赖,直接启动项目回报如下错误:
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
修改我们的实体类User
:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class User implements Serializable {
/** 用户的唯一标识 */
@Id
private Long id;
private String name;
private Integer age;
}
注意
:我们要在实体类上添加@Entity
和@Id
注解,同时要实现Serializable
,不然我们之后在浏览器端进行用户创建操作的时候无法在h2中自动创建表。
删除原有的 impl
包及其包中的内容,修改 UserRepository
,使其继承JPA的CrudRepository
接口:
public interface UserRepository extends CrudRepository<User, Long> {
}
同时我们还要修改UserController
,使其使用CrudRepository
提供的默认方法:
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository userRepository;
/**
* 从 用户存储库 获取用户列表
*
* @return
*/
private List<User> getUserList() {
List<User> list = new ArrayList<>();
Iterable<User> users = userRepository.findAll();
users.forEach(user -> {
list.add(user);
});
return list;
}
/**
* 查询所用用户
*
* @param model
* @return
*/
@GetMapping
public ModelAndView list(Model model) {
model.addAttribute("userList", this.getUserList());
model.addAttribute("title", "用户管理");
return new ModelAndView("users/list", "userModel", model);
}
/**
* 根据id查询用户
*
* @param id
* @param model
* @return
*/
@GetMapping("{id}")
public ModelAndView view(@PathVariable("id") Long id, Model model) {
Optional<User> user = userRepository.findById(id);
model.addAttribute("user", user);
model.addAttribute("title", "查看用户");
return new ModelAndView("users/view", "userModel", model);
}
/**
* 获取 form 表单页面
*
* @param model
* @return
*/
@GetMapping("/form")
public ModelAndView createForm(Model model) {
model.addAttribute("user", new User());
model.addAttribute("title", "创建用户");
return new ModelAndView("users/form", "userModel", model);
}
/**
* 新建用户
*
* @param user
* @return
*/
@PostMapping
public ModelAndView create(User user) {
user = userRepository.save(user);
return new ModelAndView("redirect:/users");
}
/**
* 删除用户
*
* @param id
* @param model
* @return
*/
@GetMapping(value = "delete/{id}")
public ModelAndView delete(@PathVariable("id") Long id, Model model) {
userRepository.deleteById(id);
model.addAttribute("userList", this.getUserList());
model.addAttribute("title", "删除用户");
return new ModelAndView("users/list", "userModel", model);
}
/**
* 修改用户
*
* @param id
* @param model
* @return
*/
@GetMapping(value = "modify/{id}")
public ModelAndView modifyForm(@PathVariable("id") Long id, Model model) {
Optional<User> user = userRepository.findById(id);
model.addAttribute("user", user);
model.addAttribute("title", "修改用户");
return new ModelAndView("users/form", "userModel", model);
}
}
同时我们在application.properties
文件中添加h2的web访问配置,这样我们就可以在浏览器端访问内存数据库:
# 使用 h2 的控制台,便于我们在web端访问内存数据库,
spring.h2.console.enabled=true
启动我们的应用,访问 http://localhost:8080/users 创建几条数据,然后在浏览器访问 http://localhost:8080/h2-console ,可以看到h2的控制界面:
image-20191127215227122默认是没有密码的,我们直接点击 Connect
就可以连接上。 注意:JDBC URL
默认是jdbc:h2:~/test
,而Spring Boot的默认数据库url应该是jdbc:h2:mem:testdb
,否则进去后找不到JPA创建的数据表,如果连接报错,一般是JDBC URL
错误,我们可以在启动日志中找到我们的内存数据库的地址:
我们点击 Connect
后可以看到下面的界面:
6.5、数据持久化实战
我们接着上一节的项目来学习,在6.4节我们将数据保存到了内存数据库h2
中。但是在实际的生产环境中,我们是不可能将数据保存在内存中的,而是持久化到Mysql
等数据库中。这一节我们就介绍如何将数据保存到mysql中。
修改application.properties
,添加数据源:
# DataSource
spring.datasource.url=jdbc:mysql://localhost/blog?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA 打印sql
spring.jpa.show-sql = true
# 在应用每次启动时删除数据库重新创建
spring.jpa.hibernate.ddl-auto=create-drop
安装启动 Mysql Server
:
安装mysql可以选择在本地安装,也可以选择安装在linux虚拟机中,或者在虚拟机中安装docker,使用docker容器安装都可以,这里不过多叙述,读者请自行安装准备好。
在 Mysql
数据库中创建blog
数据库:
CREATE DATABASE blog;
启动项目,我们可以看到在idea
的控制台打印了如下信息:
Hibernate: drop table if exists user
Hibernate: create table user (id bigint not null auto_increment, age integer, name varchar(255), primary key (id)) engine=InnoDB
打开数据库管理器可以看到JPA
自动帮我们在数据库中创建了数据表:
我们在浏览器端访问我们的项目界面,插入数据,可以看到用户信息被持久化到了mysql
中。而我们访问 http://localhost:8080/h2-console 查看我们的内存数据库,发现内存数据库是无法进入的,因为这个时候我们指定了数据源为mysql数据库,因此内存数据库中就不会存在数据库表,我们在控制台也可以看到如下信息:
H2 console available at '/h2-console'. Database available at 'jdbc:mysql://localhost/blog?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
以上,就是我们有关Spring Data JPA 的简单介绍,更多内容我们在之后的使用中还会讲到。更对内容可以查看源代码获取。
网友评论