Spring Data JPA渐进式学习--如何自定义查询方法呢?
1 定义查询方法的配置和使用方法
在Spring Data JPA中可以直接通过方法名实现CRUD
通过方法名实现CRUD
想要通过方法名实现CRUD的话,需要让我们的UserRepisitory
继承CrudRepository
,如下所示
public interface UserRepository extends CrudRepository<UserInfo,Integer> {
}
然后在service层就可以调用UserRepository
里的方法了
选择性暴露CRUD方法
有时候我们不希望所有的方法都暴露出来,当有些数据只想被查看而不想被修改的时候,就可以如此。
具体操作就是,继承Repository类,自己写方法。
public interface UserRepository extends Repository<UserInfo,Integer> {
UserInfo findOne();
List<UserInfo> findAll();
}
这时在controller
里调用的话,就只有这两个方法了。
2 方法的查询策略设置
通过@EnableJpaRepositories
可以配置方法的查询策略,这个一般不会更改,默认的就可以。
@EnableJpaRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)
这里可以选择的QueryLookupStrategy.Key
的值共有三个
Create
Create 直接根据方法名进行创建,如UserInfo findByAgeAndName();
会删除findBy
字符,然后解析Age
,And
,Name
.若是方法名不符合规则,则会报错。在这种策略模式下,配置了@Query也是没用的,只会解析方法名。
USE_DECLARED_QUERY
声明方式创建,这种策略模式下,必须配置Query,如下所示,并不会去解析方法名,
@Query("select u from UserInfo u")
UserInfo getAllList();
CREATE_IF_NOT_FOUND
这个则是以上两种情况的综合,会先去声明方式进行创建,若是没有,则解析方法名来创建一个查询。若是两者都不满足,则启动会报错。这是默认的查询策略。
3 定义查询方法的语法
带查询功能的方法名由查询策略+查询字段+一些限制性条件
语义清晰,功能完整。下表是DMQ语法常用的关键字列表。

再举一两个例子来说明一下。
//去重,and的用法
List<UserInfo> findDistinctByAddressAndName();
//根据name查找,并根据ID进行逆序排列
List<UserInfo> findByNameOrderByIdDesc();
虽然表中都是以find开头的,但是JPA还支持read,get,query,stream,count,exist,delete,remove等前缀,如字面意思一样使用即可。
4 特定类型的参数:Sort和Pageable
为了支持排序和分页,JPA支持了两个特殊类型的参数,Sort和Pageable。
Sort在查询的时候可以实现动态排序,并且决定了字段排序的方向。 Pageable可以实现分页和排序的双重效果。
接口定义方法与说明:
1 分页和总数
Page<UserInfo> findByName(String name, Pageable pageable);
这个返回将包含可用的元素和页面的总数,这个会默认执行一个count的语句,所以性能较低。
2 分页
Slice<UserInfo> findByName(String name, Pageable pageable);
返回结果是Slice,只查询结果不关心总数。
3 排序
List<UserInfo> findByName(String name, Sort sort);
只需要排序的时候可以这样操作,添加一个Sort参数即可。
4 排序和分页
List<UserInfo> findByName(String name, Pageable pageable);
这种情况下将只返回限制查询的结果,而其他的信息不做返回。
当在service层使用的时候,可以如下操作
//查询name是Luke的第一页,每页10个信息,并返回一共有多少页
Page<UserInfo> userList = userRepository.findByName("Luke",PageRequest.of(1,10));
//查询name是Luke的第一页的10条数据
Slice<UserInfo> userList = userRepository.findByName("Luke",PageRequest.of(1,10));
//查询name是Luke的数据,并按照age的逆序排列
List<UserInfo> userList = userRepository.findByName("Luke",new Sort(Sort.Direction.DESC,"age"));
//查询name是Luke的数据,取第一页的10条数据,并按照age的逆序排列
List<UserInfo> userList = userRepository.findByName("Luke",PageRequest.of(1,10,Sort.Direction.DESC,"age"));
5 限制查询结果:Fist和Top
当只想取前几天数据的时候,可以使用First和Top关键字。
举例说明
//按照name字段顺序排列,取第一个值
UserInfo findFirstByOrderByNameAsc();
//根据Id逆序排列并取第一个值
UserInfo findTopByOrderByIdDesc();
//排序后取前10个
List<UserInfo> findFirst10ByAge(Integer age,Sort sort);
值得注意的是:
- 查询的时候可以在top和first后边跟数字表示需要多少个值。
- 若是没有数字,默认就是1
- 若是由Pageable参数,则以Top和First后边的数字为准
- 也支持Distinct关键字
6 @NotNull @NonNullApi和@Nullable
@NotNull
用于不能为空的参数或者返回值
@NonNullApi
可以定义在包上,用于表示返回值的默认行为是不接受空值的
@Nullable
用于可以为空的参数或者返回值
以下代码表示,表示参数和返回值都可以是空了。
@Nullable
UserInfo findByName(@Nullable String name);
转载自:https://juejin.cn/post/7136566779282718751