Spring Data JPA 持久层操作
- 持久层即Repository层,也叫Dao层
- Spring Data JPA 是 Spring Data 技术下的子项目,使用 Spring Data JPA 访问数据只需要数据访问层接口继承 JpaRepository 接口即可。JpaRepository 接口继承了 PagingAndSortingRepository,QueryByExampleExecutor 接口,所以拥有了它们的 CRUD 操作功能。持久层真正起作用的是接口对应的实现类,在程序执行的过程中,帮我们动态地生成了接口的实现类对象,通过 JdkDynamicAopProxy 创建动态代理对象 Simp
leJpaRepository,执行对数据库的一系列操作。持久层对数据库的操作有接口中默认继承方法、关键字抽象方法、自定义查询语句(JPQL)、原生 SQL
默认继承方法
定义 | 参数 | 返回值 | 说明 |
| 对象 | 对象 | 保存 |
| 对象 | 对象 | 保存,并强制同步到DB中 |
| 对象列表 | 对象列表 | 批量保存 |
| 对象列表 | 可迭代容器 | 批量保存 |
| ID | void | 删除一个 |
| 对象 | void | 删除一个 |
| 对象列表 | void | 批量删除,后台执行时,一条一条删除 |
| 对象列表 | void | 批量删除,后台执行时,生成一条语句执行,用多个OR条件 |
| void | void | 删除所有,后台执行时,一条一条删除 |
| void | void | 删除所有,执行一条语句 |
| ID | 对象 | 查找一个对象,对象不存在时,返回null |
| ID | 对象引用 | 查找一个对象,对象不存在时,返回不是null,但各个属性值是null |
| ID列表 | 对象列表 | 查找一批对象 |
| void | 对象列表 | 查找所有对象 |
| void | 对象列表 | 查找所有对象,并排序 |
| void | Page | 查找所有对象,并分页和排序 |
| ID列表 | 可迭代容器 | 查找一批对象 |
| void | 可迭代容器 | 查找所有对象,并排序 |
| ID | boolean | 判断对象是否存在 |
| void | long | 计算总数量 |
| void | void | 强制同步DB |
关键字抽象方法
Spring Data JPA 支持将条件属性定义在数据访问层接口下的方法名中
- 命名约定
1. 条件属性通过条件关键字连接
2. 条件属性的首字母必须大写 - Spring Data JPA 解析方法名的原则
框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如 find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是 Sort 或者 Pageable 类型,也会提取相关的信息,以便按规则进行排序或者分页查询。如下表列举部分关键字抽象方法的含义:
Keyword | Sample | JPQL snippet |
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastNameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Between | findByStartDateBetween | … where x.startDate between 1? and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate > ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
NotNull、IsNotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFristnameLike | … where firstname like ?1 |
NotLike | findByFristnameNotLike | … where firstname not like ?1 |
StartingWith | findByFristnameStartingWith | … where x.firstname like ?1(parameter bound with appended %) |
EndingWith | findByFristnameEndingWith | … where x.firstname like ?1(parameter bound with prepended % |
Containing | findByFristnameContaining | … where x.firstname like ?1(parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection age) | … where age in ?1 |
NotIn | findByAgeNotIn(Collection age) | … where age not in ?1 |
True | findByActiveTrue | … where x.active = true |
False | findByActiveFalse | … where x.active = false |
- And:等价于 SQL 中的
AND
关键字,比如findByUsernameAndPassword(String user, Striang pwd)根据用户名字和密码查找 - Or :等价于 SQL 中的
OR
关键字,比如 findByUsernameOrAddress(String user, String addr)根据用户名或地址查找 - Between:等价于 SQL 中的
BETWEEN
关键字,比如findBySalaryBetween(int max, int min)查询薪资在min 和 max 之间 - LessThan:等价于 SQL 中的
<
,比如findBySalaryLessThan(int max) - GreaterThan:等价于 SQL 中的
>
,比如 findBySalaryGreaterThan(int min) - IsNull:等价于 SQL 中的
IS NULL
,比如 findByUsernameIsNull(); - IsNotNull:等价于 SQL 中的
IS NOT NULL
,比如findByUsernameIsNotNull() - NotNull:与 IsNotNull 等价
- Like:等价于 SQL 中的
LIKE
,比如 findByUsernameLike(String user) - NotLike:等价于 SQL 中的
NOT LIKE
,比如 findByUsernameNotLike(String user) - OrderBy:等价于 SQL 中的
OREDR BY
,比如 findByUsernameOrderBySalaryAsc(String user) - Not: 等价于 SQL 中的
<>
,比如 findByUsernameNot(String user) - In:等价于 SQL 中的
IN
,比如 findByUsernameIn(Collection userList) ,方法的参数可以是 Collection类型,也可以是数组或者不定长参数 - NotIn:等价于 SQL 中的
NOT IN
,比如findByUsernameNotIn(Collection userList) ,方法的参数可以是Collection 类型,也可以是数组或者不定长参数
自定义语句(JPQL)
说明:JPQL 不支持 INSERT 语句@Query
注解中的Student
:表示实体类、studentId
:表示实体类中的属性
- 索引参数
索引值从?1
开始,查询中?X
个数需要与方法定义的参数个数相一致, 并且顺序也要一致
1.查询语句的的使用(SELECT)
例:通过学生编号查询学生
// 方法名可以自定义
@Query("select s from Student s where studentId = ?1")
Student findStudentById(Integer studentId);
2.更新语句的的使用(DELETE、UPDATE)
例:通过学生编号删除学生
// 方法名可以自定义
@Transactional
@Modifying
@Query("delete Student where studentId=?1")
int deleteById(Integer studentId);
例:通过学生编号修改学生姓名
// 方法名可以自定义
@Transactional
@Modifying
@Query("update Student s set studentName=?1 where studentId=?2")
int updateNameById(String studentName,Integer studentId);
说明:要执行更新操作,将 JPQL 语句放到@Query
注解中,还要结合@Modifying
注解才可以识别执行更新操作,还需要使用@Transcational
进行事务处理,三个注解缺一不可
- 命名参数
赋值时采用@Param("paramName")
,无顺序要求@Query
注解中,用:paramName
来接收参数
1.自定义查询语句的的使用(SELECT)
例:通过学生姓名模糊查询
// 方法名可以自定义
@Query("select s from Student s where studentName like %:name% ")
List<Student> queryByName(@Param(value = "name") String studentName);
2.自定义更新语句的的使用(INSERT、DELETE、UPDATE)
例:通过学生编号修改学生姓名
// 方法名可以自定义
@Transactional
@Modifying
@Query("update Student s set studentName=:name where studentId=:id")
int updateNameById(@Param(value="name")String studentName,@Param(value="id")Integer studentId);
原生SQL
使用方式和JPQL的使用方式基本一样,其中@Query
中的value
属性不能省略,并且要开启nativeQuery
属性
例:通过学生编号修改学生姓名
// 方法名可以自定义
@Transactional
@Modifying
@Query(value="update student set student_name=?1 where student_id=?2",nativeQuery = true)
int updateNameById(String studentName,Integer studentId);