欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【Spring Data 系列学习】Spring Data JPA @Query 注解查询

程序员文章站 2022-09-04 19:05:39
【Spring Data 系列学习】Spring Data JPA @Query 注解查询 前面的章节讲述了 Spring Data Jpa 通过声明式对数据库进行操作,上手速度快简单易操作。但同时 JPA 还提供通过注解的方式实现,通过将 注解在继承 repository 的接口类方法上 。 Qu ......

【spring data 系列学习】spring data jpa @query 注解查询

前面的章节讲述了 spring data jpa 通过声明式对数据库进行操作,上手速度快简单易操作。但同时 jpa 还提供通过注解的方式实现,通过将 @query 注解在继承 repository 的接口类方法上 。

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 "";
}

快速上手

项目中的pom.xmlapplication.properties与 chapter1 相同

实体类映射数据库表

user 实体类

@entity
@table(name = "t_user")
public class user implements serializable {

    private static final long serialversionuid = 1l;
    @id
    @generatedvalue(strategy = generationtype.identity)
    private long id;

    @column(name = "u_name")
    private string name;

    @column(name ="u_age")
    private integer age;
    
    @column(name ="u_email")
    private string email;

    // 省略构造器 set/get        

}

@entity:定义对象将会成为被jpa管理的实体,将映射到指定的数据库表。

@table :指定数据库的表名。

@column:定义该属性对应数据库中的列名。

@id 定义属性为数据库的主键,一个实体里面必须有一个。

@generatedvalue(strategy = generationtype.identity) 自增长 id 策略

生成如下:

【Spring Data 系列学习】Spring Data JPA @Query 注解查询

@query 查询

基本使用

继承 userqueryrepository

public interface userqueryrepository extends jparepository<user, long> {

    /**
     *  语句中 user 查询数据表的类名,?1 括号代表第一个参数
     */
    @query(name = "select  * from user where name = ?1")
    list<user> findbyname(string name);

     /**
     * sort 排序
     *  根据姓名模糊查询排序
     */
    @query("select u from user u where u.name like ?1%")
    list<user> findbyandsort(string name, sort sort);
    
    /**
     * @transactional 事务的支持 ,@modifying 用于修改查询
     * @param name 对应 ?1
     * @param id 对应 ?2
     * @return
     */
    @transactional
    @modifying
    @query("update user u set u.name = ?1 where u.id = ?2")
    int updatebyid(string  name, long id);


}

@param用法

    /**
     *  param 对象
     * @param name
     * @param age
     * @return
     */
    @query(value = "select  u from user u where u.name = :name and u.age = :age")
    list<user> queryparambynameandage(@param("name") string name,@param("age") integer age);


    /**
     *  传一个对象
     * @param user
     * @return
     */
    @query(value = "select  u from user u  where u.name = :#{#user.name} and u.age = :#{#user.age}")
    list<user> queryobjectparambynameandage(@param("user") user user);
  • :name 对应 @param中的 name。
  • :age 对应 @param中的 age。

  • :#{#user.name} : 对象中的参数使用方法

spel表达式

@query("select u from #{#entityname} u where u.lastname = ?1")
 list<user> findbylastname(string lastname);
  • entityname: 根据指定的 repository 自动插入相关的 entityname。有两种方式能被解析出来:
    • 如果定义了 @entity 注解,直接用其属性名。
    • 如果没有定义,直接用实体类的名称。

原生 sql

    @query(value = "select * from t_user  where u_name = :name",nativequery = true)
    list<user> querynativebyname(@param("name") string name);
  • nativequery: 为 true 开启。开启之后字段则需要对应的数据库中的表名和字段。

curd 测试类

路径:src/test/java/com/mtcarpenter/repository/userqueryrepositorytest.java

@runwith(springrunner.class)
@springboottest
public class userqueryrepositorytest {

    /**
     * ⽇志对象
     */
    private logger logger = loggerfactory.getlogger(userqueryrepositorytest.class);

    @autowired
    private userqueryrepository userqueryrepository;


    @before
    public void save() {
        logger.info("新增数据 result = {}", userqueryrepository.save(new user("小米", 9, "a@qq.com")));
        logger.info("新增数据 result = {}", userqueryrepository.save(new user("张三", 16, "b@qq.com")));
        logger.info("新增数据 result = {}", userqueryrepository.save(new user("三哥", 12, "c@qq.com")));
        logger.info("新增数据 result = {}", userqueryrepository.save(new user("米二", 13, "e@qq.com")));
        logger.info("新增数据 result = {}", userqueryrepository.save(new user("阿三", 12, "f@qq.com")));
        logger.info("新增数据 result = {}", userqueryrepository.save(new user("张三", 12, "g@qq.com")));
        logger.info("新增数据 result = {}", userqueryrepository.save(new user("米二", 8, "h@qq.com")));
    }

    /**
     * 基本使用
     */
    @test
    public void test() {
        logger.info("@query 查询张三 result = {}", userqueryrepository.findbyname("张三"));
        logger.info("根据姓名模糊查询排序 result = {}", userqueryrepository.findbynameandsort("米", new sort(sort.direction.asc,"age")));
        logger.info("修改 id = 1 的name ,result ={ }", userqueryrepository.updatebyid("红米", 1l));
    }

    /**
     *  param 参数使用
     */
    @test
    public void paramtest(){
        logger.info("@param 使用方法  result = {}",userqueryrepository.queryparambynameandage("张三", 12));
        user user = new user();
        user.setname("张三");
        user.setage(12);
        logger.info("@param 对象 result = {}", userqueryrepository.queryobjectparambynameandage(user));
    }

    /**
     * spel 使用
     */
    @test
    public void speltest(){
        logger.info("spel 使用方法  result = {}",userqueryrepository.queryelbyname("张三"));
    }

    /**
     * 原生查询
     */
    @test
    public void nativetest(){
        logger.info("原生查询 使用方法  result = {}",userqueryrepository.querynativebyname("张三"));

    }
}

本章代码

  • github: