Spring Data JPA @Query详解

584 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1、@Query注解源码

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@QueryAnnotation
@Documented
public @interface Query {
    // 指定JPQL的查询语句,(nativeQueryt = true时,使用原生SQL语句)
   String value() default "";

   // 指定count的JPQL语句,如果不指定将根据query自动生成 (nativeQueryt = true时,使用原生SQL语句)
   String countQuery() default "";

   // 根据哪个字段来count,一般默认即可
   String countProjection() default "";

   // 默认是false,表示value里面是不是原生的sql语句
   boolean nativeQuery() default false;

   // 可以指定一个query名字,必须唯一的。 如果不指定,默认的生成规则是:{$domainClass}.${queryMethodName}
   String name() default "";

   // 可以指定一个count的query的名字,必须唯一的。如果不指定,默认的生成规则是{$domainClass}.${queryMethodName}.count
   String countName() default "";
}

1.1 countQuery

介绍: 定义一个特殊的count查询,用于分页查询时,查找页面元素的总个数。如果没有配置,将根据方法名派生一个count查询。

作用: countQuery用于分页,如果要求分页结果返回正确的总计数。@Query注解可以在countQuery属性中与计数查询一起提供。此查询在结果查询之后单独执行,其结果用于填充返回的Page 的 totalElements属性

目前Spring-Data-JPA不支持对nativeQuery=true时的Sort动态排序

@Query(value = "SELECT * FROM user as u WHERE u.name Like :name ", nativeQuery = true)
List<User> findByNameLike123(String name, Sort sort);

会出现以下错误:Cannot use native queries with dynamic sorting in method public abstract

image.png

但是我们可以传入Pageable,来解决nativeQuery=true时的Sort动态排序

@Query(value = "SELECT * FROM user as u WHERE u.name Like :name ",
        countQuery = "SELECT COUNT(*) FROM user as u WHERE u.name Like :name",
        nativeQuery = true)
Page<User> findByNameLike12(String name, Pageable pageable);

2、@Query的基本用法

@Query用法是使用JPQL为实体创建声明式查询方法。我们一般只需要关心@Query里面的value和nativeQuery、countQuery的值即可,其他的都不太常用。

// 根据地址查询 (:address属于@Query的动态参数)
@Query("FROM User as u WHERE u.address = :address")
User findByAddress(String address);

// 模糊查询
@Query(value = "FROM User u WHERE u.name LIKE ?1%")
Page<User> findByNameLikePage(String name, Pageable pageable);

// 使用原生SQL
@Query(value = "SELECT * FROM user WHERE name = ?1 And id = ?2",nativeQuery = true)
List<User> findByNameAndId(String name,int id,Pageable 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);

3、@Param的基本用法

@Param注解指定方法参数的具体名称,通过绑定的参数名字指定查询条件,这样就不需要关心参数的顺序

@Query(value = "select * from User where user_id = :id", nativeQuery = true)
List<User> findUser(@Param(value = "id") String userId);

4、小结

  • 能用方法名表示的,尽量用方法名表示,因为这样语义清晰、简单快速,基本上只要编译通过,一定不会有问题。

  • 能用@Query里面的JPQL表示的,就用JPQL表示,这样与SQL无关。万一换数据库了,代码基本上不用改变

  • 如果实在没招了,就用nativeQuery写原始SQL