本文已参与「新人创作礼」活动,一起开启掘金创作之路。
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
但是我们可以传入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