一、什么是JPA
1.JPA的定义和基本概念
JPA(Java Persistence API)是Java中用于进行持久化操作的一种规范,它定义了一系列用于操作关系型数据库的API接口。通过这些接口,开发人员可以方便地进行数据库的增删改查等操作,而无需关注具体的数据库操作细节。JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
2.JPA的核心概念
JPA的核心概念包括对象-关系映射(ORM)和实体对象持久化。ORM技术是一种将对象模型和关系模型进行映射的技术,通过ORM,开发人员可以将Java对象直接映射到数据库表中,从而避免了手动编写SQL语句的繁琐工作。JPA提供了一套注解和配置方式,可以方便地将Java类与数据库表进行映射,使得开发人员可以直接操作Java对象,而无需手动维护SQL语句。
3.JPA的用途和目标
JPA的目标是简化企业应用开发,使得开发者能够更容易地实现对象与数据库表之间的映射关系。它定义了对象-关系映射(ORM)以及实体对象持久化的标准接口,旨在规范和简化Java对象的持久化工作。通过提供统一的API和封装数据库操作细节,JPA使得开发人员可以更加方便地进行数据库操作,提高了代码的可维护性和可读性。
4.JPA的优势
使用JPA的优势包括提高代码的可维护性和可读性。通过使用JPA,开发人员可以使用面向对象的方式来操作数据库,无需直接操作SQL语句,这使得代码更加直观和易于理解。此外,JPA还提供了一些高级特性,如缓存管理、事务管理等,这些特性可以帮助开发人员更好地进行性能优化和并发控制。
二、JPA的使用
1.准备数据库脚本
sql
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
2.初始化数据
sql
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
3.xml文件导入依赖
java
<!-- JPA框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
4.引入JPA配置
java
spring:
jpa:
hibernate:
# ddl-auto 枚举:
# none(默认):禁用DDL处理
# validate:验证schema,不对数据库做任何操作
# update:更新schema
# create:创建schema,并销毁之前数据
# create-drop:会话创建时创建schema,会话关闭时销毁schema
ddl-auto: update
# jpa配置:在控制台显示Hibernate的sql(可选)
show-sql: true
(1)加载数据库驱动,springboot3.0开始mysql驱动改为com.mysql.cj.jdbc.Driver,而非com.mysql.jdbc.Driver。
(2)jpa底层实现采用hibernate,自动建表配置使用update,表示第一次创建schema,后续只做更新操作。
5.创建实体对象
java
import lombok.Data;
import javax.persistence.*;
@Entity
@Data
@Table(name = "user")
public class UserDO {
private static final long serialVersionUID = -2952735933715107252L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer age;
private String email;
}
6.定义Repository接口
java
public interface UserRepository extends JpaRepository<UserDO, Long> {
/**
* 根据用户姓名查找用户
*
* @param name 用户姓名
* @return 找到的用户对象,如果不存在返回 null
*/
UserDO findByName(String name);
/**
* 根据用户姓名或电子邮箱查找用户
*
* @param name 用户姓名
* @param email 用户电子邮箱
* @return 找到的用户对象,如果不存在返回 null
*/
UserDO findByNameOrEmail(String name, String email);
/**
* 根据用户姓名计数用户数量
*
* @param name 用户姓名
* @return 具有该姓名的用户数量
*/
Long countByName(String name);
/**
* 根据用户名进行模糊搜索
*
* @param name 用户姓名(可以包含通配符)
* @return 匹配的用户列表
*/
List<UserDO> findByNameLike(String name);
/**
* 根据用户姓名忽略大小写查找用户
*
* @param name 用户姓名
* @return 找到的用户对象,如果不存在返回 null
*/
UserDO findByNameIgnoreCase(String name);
/**
* 根据用户姓名查找用户,并按年龄降序排列
*
* @param name 用户姓名
* @return 匹配的用户列表,按年龄降序排列
*/
List<UserDO> findByNameContainingOrderByAgeDesc(String name);
/**
* 根据用户姓名进行分页查询
*
* @param name 用户姓名
* @param pageable 分页信息
* @return 包含用户对象的分页结果
*/
Page<UserDO> findByName(String name, Pageable pageable);
}
注:Repository接口用于定义对实体对象UserDO进行持久化操作的方法。
7.创建controller层调用Repository接口方法
这里只是简单测了根据ID查询
java
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserRepository userRepository;
/**
* 测试单条查询
*/
@GetMapping("/id")
public void testSelectOne() {
// 从 UserRepository 中查找 ID 为 1 的用户
Optional<UserDO> user = userRepository.findById(1L);
System.out.println(user);
}
}
测试效果:
三、JPA的常用
1.常用注解
|-----------------|-------------------------------------------------------|
| 注解 | 描述 |
| @Entity | 声明该类为实体类。 |
| @Table | 指定实体类映射的数据库表,通常与@Entity注解一起使用。 |
| @Id | 声明实体类的属性或字段作为数据库表的主键。 |
| @GeneratedValue | 指定主键的生成策略。 |
| @Column | 用于标注实体类中的属性与数据库表中的字段之间的映射关系。 |
| @Transient | 声明实体类的属性或字段不是持久化的。 |
| @Basic | 指定实体类属性的存取策略。 |
| @Temporal | 指定java.util.Date或java.util.Calendar 属性映射到数据库类型时的时间精度。 |
| @Enumerated | 指定枚举类型的属性映射。 |
| @OneToOne | 指定一对一的关联映射。 |
| @OneToMany | 指定一对多的关联映射。 |
| @ManyToOne | 指定多对一的关联映射。 |
| @ManyToMany | 指定多对多的关联映射。 |
| @JoinColumn | 指定关联的外键列。 |
| @MapKey | 指定映射关系中的键。 |
2.常用查询方法
|--------|------------------------------|---------------------------|
| 方法类型 | 方法名称 | 描述 |
| 查询方法 | findBy/getBy/queryBy/readBy | 后面跟要查询的字段名,用于精确匹配。 |
| 查询方法 | find/get/query/read | 后面跟要查询的字段名,使用条件表达式进行模糊匹配。 |
| 查询方法 | findAll/getAll | 不跟字段名,表示查询所有记录。 |
| 支持的关键字 | And | 连接多个查询条件,相当于 SQL 中的 AND。 |
| 支持的关键字 | Or | 连接多个查询条件,相当于 SQL 中的 OR。 |
| 支持的关键字 | Between | 查询字段在某个范围内的记录。 |
| 支持的关键字 | LessThan/LessThanEqual | 查询字段小于或小于等于某个值的记录。 |
| 支持的关键字 | GreaterThan/GreaterThanEqual | 查询字段大于或大于等于某个值的记录。 |
| 支持的关键字 | IsNull/IsNotNull | 查询字段为空或不为空的记录。 |
| 支持的关键字 | Like/NotLike | 模糊查询字段值。 |
| 支持的关键字 | OrderBy | 指定查询结果的排序方式。 |
| 删除方法 | deleteBy/removeBy | 后面跟要查询的字段名,用于精确匹配。 |
| 删除方法 | delete/remove | 后面跟要查询的字段名,使用条件表达式进行模糊匹配。 |
| 统计方法 | countBy | 后面跟要查询的字段名,用于精确匹配。 |
| 统计方法 | count | 不跟字段名,表示统计所有记录数。 |
| 更新方法 | updateBy | 后面跟要查询的字段名,用于精确匹配。 |
| 更新方法 | update | 后面跟要查询的字段名,使用条件表达式进行模糊匹配。 |
| 支持的关键字 | Set | 设置要更新的字段的值。 |
| 支持的关键字 | Where | 指定更新操作的条件。 |
3.部分查询关键字映射示例
|-------------------|-----------------------------------------|
| 部分查询关键字映射示例 ||
| 关键字 | 使用示例 |
| And | findByLastnameAndFirstname |
| Or | findByLastnameOrFirstname |
| Is,Equals | findByFirstnameIs,findByFirstnameEquals |
| Between | findByStartDateBetween |
| LessThan | findByAgeLessThan |
| LessThanEqual | findByAgeLessThanEqual |
| GreaterThan | findByAgeGreaterThan |
| GreaterThanEqual | findByAgeGreaterThanEqual |
| After | findByStartDateAfter |
| Before | findByStartDateBefore |
| IsNull | findByAgeIsNull |
| IsNotNull,NotNull | findByAge(Is)NotNull |
| Like | findByFirstnameLike |
| NotLike | findByFirstnameNotLike |
| StartingWith | findByFirstnameStartingWith |
| EndingWith | findByFirstnameEndingWith |
| Containing | findByFirstnameContaining |
| OrderBy | findByAgeOrderByLastnameDesc |
| Not | findByLastnameNot |
| In | findByAgeIn(Collection ages) |
| NotIn | findByAgeNotIn(Collection ages) |
| TRUE | findByActiveTrue() |
| FALSE | findByActiveFalse() |
| IgnoreCase | findByFirstnameIgnoreCase |