Spring Data JPA渐进式学习--如何自定义查询方法呢?

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

1 定义查询方法的配置和使用方法

在Spring Data JPA中可以直接通过方法名实现CRUD

通过方法名实现CRUD

想要通过方法名实现CRUD的话,需要让我们的UserRepisitory继承CrudRepository,如下所示

public interface UserRepository extends CrudRepository<UserInfo,Integer> {

}
复制代码

然后在service层就可以调用UserRepository里的方法了

image.png

选择性暴露CRUD方法

有时候我们不希望所有的方法都暴露出来,当有些数据只想被查看而不想被修改的时候,就可以如此。

具体操作就是,继承Repository类,自己写方法。

public interface UserRepository extends Repository<UserInfo,Integer> {
    UserInfo findOne();
    List<UserInfo> findAll();
}
复制代码

这时在controller里调用的话,就只有这两个方法了。

image.png

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语法常用的关键字列表。

20191122172557317.png

再举一两个例子来说明一下。

//去重,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);
复制代码

猜你喜欢

转载自juejin.im/post/7136566779282718751