1、什么是DMQ?
DMQ (Defining Query Method) 定义查询方法。若想要实现CRUD操作,无需再写一大堆SQL语句,直接通过方法名就可以实现查询,如下所示
public interface UserRepo extends CrudRepository<User,Integer>, PagingAndSortingRepository<User,Integer> , JpaRepository<User, Integer> {
// 根据用户id和地址查询
User findByIdAndAddress(int id,String address);
}
当不想暴露CrudRepository的所有方法时,我们可以自定义一个MyBaseRepository 然后继承Repository接口实现自己想要的方法,也可以选择SimpleJpaRepository中任意某个已经实现的方法。
public interface MyBaseRepo<T,ID extends Serializable> extends Repository<T,ID> {
T findOne(ID id);
T save(T entity);
}
public interface UserRepo extends MyBaseRepo<User,Integer> {
User findByIdAndAddress(int id,String address);
}
2、方法的查询策略设置
为什么可以通过方法名或@Query也可以实现查询呢?
我们可以通过注解@EnableJpaRepositories可配置方法的查询策略
@EnableJpaRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)
- Create:直接根据方法名进行创建。如果方法名不符合规则,启动的时候会报异常,这种情况可以理解为即使配置了@Query也是没用的
- USE_DECLARED_QUERY:声明方式创建,可以理解为必须配置@Query。如果没有找到声明查询,将抛出一个异常。
- CREATE_IF_NOT_FOUND:默认使用,兼容以上两种方式。先用声明方式(@Query)进行查找,如果没有找到与方法相匹配的查询,那就用Create的方法名创建规则来创建一个查询。如果都没有找到,启动就会报错。
3、定义查询方法的语法
语法: 查询策略(关键字)+ 查询字段 + 限制性条件
最重要的一点: 方法名的表达式通常是实体属性连接运算符的组合
3、特定类型的参数:Sort和Pageable
在上一文中我们介绍了Sort和Pageable在PageingAndSortingRepository接口中的使用。本文将会介绍Sort、Pageable在DMQ中的使用。
在DMQ中使用Sort和Pageable是非常简单的,直接作为参数传入到自定义方法中。
@Query(value = "FROM User u WHERE u.name LIKE ?1%")
List<User> findByNameLike(String name, Sort sort);
@Query(value = "FROM User u WHERE u.name LIKE ?1%")
List<User> findByNameLike(String name, Pageable pageable);
4、限制查询结果:First和Top
场景: 有的时候我们想直接查询前几条数据,也不需要动态排序,就可以简单地在方法名字中使用First和Top关键字,来限制返回条数
// 返回前三条数据
List<User> findTop3ByNameLike(String name);
// 返回前四条数据
List<User> findFirst4ByNameLike(String name);
注意:
- 查询方法在使用First或Top时,数值可以追加到First或Top后面,指定返回最大结果的大小。
- 如果数字被省略、则假设结果大小为1。
- 如果将Pageable作为参数,以Top或First后面的数字为准,即分页将在限制结果中应用
5、@NonNUll、@NonNullApi 和 @Nullable 关键字
- @NonNull:用于不能为空的参数或返回值
List<User> findTop3ByNameLike(@NonNull String name);
-
@NonNullApi:在包级别用于声明参数,以及返回值的默认行为是不接受空值或产生空值的。
-
@Nullable: 用于可以为空的参数或返回值
@Nullable
List<User> findFirst4ByNameLike(String name);