注解(声明式)查询语法
@Query 详解
源码
public @interface Query { // JPQL 查询语句,当 nativeQuery=true时,是原生SQL语句 String value() default ""; // 指定count的JPQL语句,如果不能指定将根据query自动生成 // nativeQuery=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 ""; }
@Query 用法
JPQL在启动的时候就知道语法正确与否
@Query 排序
JPQL排序
@Query("select u from t_user u")
List<SystemUser> findUser(Sort sort);
nativeQuery排序
nativeQuery 不支持直接Sort的参数查询,Sort查询参数是给JPQL使用的
nativeQuery 排序正确的写法:
@Query(value = "select * from t_user order by ?1 desc",nativeQuery = true) List<SystemUser> nativeQueryOrderBy(String orderByFiledName);
@Query分页
JPQL分页
// 直接使用 Pageable 参数 @Query("select u from t_user u") List<SystemUser> findUser(Pageable pageable);
nativeQuery分页
// 必须要有 /* #pageable# */ 注释 @Query(value = "select * from t_user order by ?1 desc /* #pageable# */",nativeQuery = true) List<SystemUser> nativeQueryOrderBy(String orderByFiledName);
@Param用法
用于指定参数名称
默认情况下,参数是通过顺序绑定在查询语句上的,这使得查询方法对参数位置的重构容易出错
@Query(value = "select u from t_user u where u.uname=:uname")
List<SystemUser> nativeQueryOrderBy(@Param("uname") String uname);
SpEL表达式支持
#{#entityName} 来自于 @Entity 注解中 name 或 value 的属性值 或者是 实体类名称,可以在JPQL中使用
@Modifying修改查询
在@Query上增加@Modifying 可以实现delete或者update的操作
// 修改操作 @Modifying @Query("update t_user u set u.email=:email where u.id = :id") int updateEmail(@Param("id") String id,@Param("email") String email); // 删除操作 @Modifying @Query("delete from t_user u where u.uname=?1") int deleteUser(String uname);
@Procedure 存储过程的查询方法
@Procedure的源码:
public @interface Procedure { // 存储过程的名称 String value() default ""; // 存储过程的名称 String procedureName() default ""; // 在EntityManager中的名字,NamedSoredProcedureQuery使用 String name() default ""; // 输出参数的名字 String outputParameterName() default ""; }
1.自定义的一段存储过程:
CREATE DEFINER=`root`@`%` PROCEDURE `incr`(IN `data` int, OUT val int) BEGIN set val = `data`+10; END
2.使用@NamedSortedProcedureQueries注释来调用存储过程
@Entity @NamedStoredProcedureQuery( // jpa中存储过程的名称 Incr 对应类名,inc为自定义名称 name = "Incr.inc", // 数据库中存储过程的名称 procedureName = "incr", parameters = { @StoredProcedureParameter(mode = ParameterMode.IN,name = "data",type=Integer.class), @StoredProcedureParameter(mode = ParameterMode.OUT,name = "val",type=Integer.class), } ) public class Incr { private String id; public void setId(String id) { this.id = id; } @Id public String getId() { return id; } }
3.调用映射的存储过程
注意这里的参数要和存储过程中的参数的数量和类型匹配
@Procedure(name = "Incr.inc")
Integer incr(@Param("data") Integer data);
4. 测试代码
@Test public void testProcedure(){ Assert.isTrue(this.userRepository.incr(10) == 20,"存储过程调用错误"); }
@NamedQueries预定义查询
预定义查询的一种形势
// 预定义查询 @NamedQuery(name = "SystemUser.findByUname", query = "select u from t_user u where u.uname = ?1") @Entity(name = "t_user") @Data public class SystemUser { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String uname; private String email; private String address; }
dao写法:
SystemUser findByUname(String uname);
@NameQuery、@Query方法定义查询的对比
Spring JPA的优先级: @Query > @NameQuery > 方法定义查询
推荐使用的优先级: @Query > 方法定义查询 > @NameQuery
它们都不支持动态条件查询

浙公网安备 33010602011771号