什么是Spring-Data-JPA?
JPA(Java Persistence API,Java持久化API),定义了对象-关系映射(ORM)以及实体对象持久化的标准接口。
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框和云计算数据服务。 Spring Data 包含多个子项目,Spring-data-jpa是其中一个用于简化JPA开发的框架。
Spring Data JPA的核心概念:
Repository:最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组件扫描的时候自动识别。
CrudRepository :是Repository的子接口,提供CRUD的功能
PagingAndSortingRepository:是CrudRepository的子接口,添加分页和排序的功能
JpaRepository:是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操作等。
JpaSpecificationExecutor:用来做负责查询的接口
Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可。
配置Spring-Data-JPA的使用
|
|
SpringBoot的DataSource属性的说明
|
|
Spring-Data-JPA的常用接口说明
实体类
|
|
接口
Repository
Repository 接口是 Spring Data 的一个核心接口,它不提供任何方法,开发者需要在自己定义的接口中声明需要的方法。
|
|
CrudRepository
使用 CrudRepository 的副作用是它可能暴露了你不希望暴露给业务层的方法。比如某些接口你只希望提供增加的操作而不希望提供删除的方法。针对这种情况,开发者只能退回到 Repository 接口,然后到 CrudRepository 中把希望保留的方法声明复制到继承Repository 的自定义的接口中即可。
PagingAndSortingRepository
它继承自 CrudRepository 接口,在 CrudRepository 基础上新增了两个与分页有关的方法。但是,我们很少会将自定义的持久层接口直接继承自 PagingAndSortingRepository,而是在继承 Repository 或 CrudRepository 的基础上,在自己声明的方法参数列表最后增加一个 Pageable 或 Sort 类型的参数,用于指定分页或排序信息即可,这比直接使用 PagingAndSortingRepository 提供了更大的灵活性。
JpaRepository
继承自 PagingAndSortingRepository 的针对 JPA 技术提供的接口,它在父接口的基础上,提供了其他一些方法,比如 flush(),saveAndFlush(),deleteInBatch() 等。如果有这样的需求,则可以继承该接口。
Spring Data JPA本身会提供3中方式创建查询:
通过解析方法名创建查询
Keyword | Sample | JPQL snippet |
---|---|---|
IsNotNull | findByAgeNotNull | … where x.age not null |
Like | findByNameLike | … where x.name like ?1 |
NotLike | findByNameNotLike | … where x.name not like ?1 |
StartingWith | findByNameStartingWith | … where x.name like ?1(parameter bound with appended %) |
EndingWith | findByNameEndingWith | … where x.name like ?1(parameter bound with prepended %) |
Containing | findByNameContaining | … where x.name like ?1(parameter bound wrapped in %) |
OrderBy | findByAgeOrderByName | … where x.age = ?1 order by x.name desc |
Not | findByNameNot | … where x.name <> ?1 |
In | findByAgeIn | … where x.age in ?1 |
NotIn | findByAgeNotIn | … where x.age not in ?1 |
True | findByActiveTrue | … where x.avtive = true |
Flase | findByActiveFalse | … where x.active = false |
And | findByNameAndAge | … where x.name = ?1 and x.age = ?2 |
Or | findByNameOrAge | … where x.name = ?1 or x.age = ?2 |
Between | findBtAgeBetween | … where x.age between ?1 and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
After/Before | … | … |
IsNull | findByAgeIsNull | … where x.age is null |
第一步,解析时,会先把方法名多余的前缀截取掉,比如find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。
第二步,例如findByUserDepUuid()先判断userDepUuid (根据POJO 规范,首字母变为小写)是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;
从右往左截取第一个大写字母开头的字符串此处为Uuid),然后检查剩下的字符串是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设user为查询实体的一个属性;
接着处理剩下部分(DepUuid),先判断user 所对应的类型是否有depUuid属性,如果有,则表示该方法最终是根据“ Doc.user.depUuid” 的取值进行查询;否则继续按照步骤二 的规则从右往左截取,最终表示根据“Doc.user.dep.uuid” 的值进行查询。
可能会存在一种特殊情况,比如Doc包含一个user 的属性,也有一个userDep 属性,此时会存在混淆。可以明确在属性之间加上”_” 以显式表达意图,比如”findByUser_DepUuid()” 或者”findByUserDep_uuid()”。
使用 @Query 创建查询
通过调用 JPA 命名查询语句创建查询
|
|