注解(声明式)查询语法

 

 

@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

它们都不支持动态条件查询

 

posted @ 2020-11-19 08:25  半雨微凉  阅读(367)  评论(0)    收藏  举报