Spring Data JPA 持久层操作

  • 持久层即Repository层,也叫Dao层
  • Spring Data JPA 是 Spring Data 技术下的子项目,使用 Spring Data JPA 访问数据只需要数据访问层接口继承 JpaRepository 接口即可。JpaRepository 接口继承了 PagingAndSortingRepository,QueryByExampleExecutor 接口,所以拥有了它们的 CRUD 操作功能。持久层真正起作用的是接口对应的实现类,在程序执行的过程中,帮我们动态地生成了接口的实现类对象,通过 JdkDynamicAopProxy 创建动态代理对象 Simp
    leJpaRepository,执行对数据库的一系列操作。持久层对数据库的操作有接口中默认继承方法、关键字抽象方法、自定义查询语句(JPQL)、原生 SQL

默认继承方法

定义

参数

返回值

说明

<S extends T> S save(S entiry)

对象

对象

保存

<S extends T> S saveAndFlush(S entiry)

对象

对象

保存,并强制同步到DB中

<S extends T> List<S> save(Iterable<? extends T> entities)

对象列表

对象列表

批量保存

<S extends T> Iterable<S> save(Iterable<S> entities)

对象列表

可迭代容器

批量保存

void delete(ID id)

ID

void

删除一个

void delete(I entity)

对象

void

删除一个

void delete(Iterable<? extends T> entities)

对象列表

void

批量删除,后台执行时,一条一条删除

void deleteInBatch(Iterable<T> entities)

对象列表

void

批量删除,后台执行时,生成一条语句执行,用多个OR条件

void deleteAll()

void

void

删除所有,后台执行时,一条一条删除

void deleteAllInBatch()

void

void

删除所有,执行一条语句

T findOne(ID id)

ID

对象

查找一个对象,对象不存在时,返回null

T getOne(ID id)

ID

对象引用

查找一个对象,对象不存在时,返回不是null,但各个属性值是null

List<T> findAll(Iterable<ID> ids)

ID列表

对象列表

查找一批对象

List<T> findAll()

void

对象列表

查找所有对象

List<T> findAll(Sort sort)

void

对象列表

查找所有对象,并排序

Page<T> findAll(Pageable pageable)

void

Page

查找所有对象,并分页和排序

Iterable<T> findAll(Iterable<ID> ids)

ID列表

可迭代容器

查找一批对象

Iterable<T> findAll()

void

可迭代容器

查找所有对象,并排序

boolean exists(ID id)

ID

boolean

判断对象是否存在

long count()

void

long

计算总数量

void flush()

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);