zoukankan      html  css  js  c++  java
  • Spring JPA 查询创建

    Spring JPA 查询创建

    这是JPA内容的核心部分,可以收藏用作参阅文档。

    1. 查询转化和关键字

    例:一个JPA查询的转化

    public interface UserRepository extends Repository<User, Long> {
    
      List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
    }
    

    我们使用JPA 标准API创建一个查询,但从本质上讲,这将转换为以下查询:select u from User u where u.emailAddress = ?1 and u.lastname = ?2,Spring Data JPA执行属性检查并遍历嵌套属性,如属性表达式中所述。

    下表描述了JPA支持的关键字,以及包含该关键字的方法可以转换成什么查询语句:

    表:查询关键字及对应查询语句

    关键字 样例 JPQL片段(转化的查询语句)
    And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
    Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
    Is, Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
    Between findByStartDateBetween … where x.startDate between ?1 and ?2
    LessThan findByAgeLessThan … where x.age < ?1
    LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
    GreaterThan findByAgeGreaterThan … where x.age > ?1
    GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
    After findByStartDateAfter … where x.startDate > ?1
    Before findByStartDateBefore … where x.startDate < ?1
    IsNull, Null findByAge(Is)Null … where x.age is null
    IsNotNull, NotNull findByAge(Is)NotNull … where x.age not null
    Like findByFirstnameLike … where x.firstname like ?1
    NotLike findByFirstnameNotLike … where x.firstname not like ?1
    StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (参数绑定附加 %)
    EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (参数绑定附加 %)
    Containing findByFirstnameContaining … where x.firstname like ?1 (参数绑定附加 %)
    OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
    Not findByLastnameNot … where x.lastname <> ?1
    In findByAgeIn(Collection<Age> ages) … where x.age in ?1
    NotIn findByAgeNotIn(Collection<Age> ages) … where x.age not in ?1
    True findByActiveTrue() … where x.active = true
    False findByActiveFalse() … where x.active = false
    IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

    InNotIn也接受集合的任何子类以及数组作为一个参数或可变参数。对于相同逻辑运算符的其他语法版本,请检查存储库查询关键字。

    2. 使用@Query 自定义查询

    ​ 使用自命名查询声明实体的查询是一种有效的方法,该方法适用于少量查询。由于查询本身绑定到执行它们的Java方法上,实际上可以通过使用Spring Data JPA @Query注释直接绑定,而不用将它们注释到域类。这将域类从特定于持久性的信息中解放出来,并将查询合并到该存储库接口:

    ​ 注释@Query查询优先于使用@NamedQuery定义的查询和在orm.xml中声明的自命名查询。

    例:使用@Query在查询方法上声明查询

    public interface UserRepository extends JpaRepository<User, Long> {
    
      @Query("select u from User u where u.emailAddress = ?1")
      User findByEmailAddress(String emailAddress);
    }
    

    3. 使用高级LIKE表达式

    ​ 使用@Query创建的自命名查询的查询执行机制允许在查询定义中定义高级LIKE表达式,如下面的示例所示:

    例:@Query中定义的LIKE表达式

    public interface UserRepository extends JpaRepository<User, Long> {
    
      @Query("select u from User u where u.firstname like %?1")
      List<User> findByFirstnameEndsWith(String firstname);
    }
    

    ​ 在前面的示例中,识别了LIKE的分隔符字符(%),并将查询转换为有效的JPQL查询(移除%)。在执行查询时,传递给方法调用的参数将使用之前识别的LIKE模式进行扩充。

    4. 使用原生查询

    ​ 将nativeQuery标志设置为true, @Query注释允许运行原生查询,如下面的示例所示:

    例:使用@Query在查询方法上声明一个原生查询

    public interface UserRepository extends JpaRepository<User, Long> {
    
      @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
      User findByEmailAddress(String emailAddress);
    }
    

    Spring Data JPA目前不支持原生查询的动态排序,因为它必须操作声明的实际查询,而这对本地SQL来说是不可靠的。但是,您可以通过自己指定count查询来对本机查询的结果进行分页,如下面的示例所示:

    例:通过使用@Query在查询方法上声明用于分页的本机计数查询

    public interface UserRepository extends JpaRepository<User, Long> {
    
      @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
        countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
        nativeQuery = true)
      Page<User> findByLastname(String lastname, Pageable pageable);
    }
    

    5.使用Sort

    ​ 我们可以通过PageRequestSort直接完成排序,SortOrder实例中实际使用的属性需要与您的域模型(持久化模型)匹配。这意味着它们需要解析为查询中使用的属性或别名。JPQL将其定义为状态字段路径表达式。

    使用任何不可引用的路径表达式都会导致异常。

    ​ 但是,使用Sort@Query可以让您插入包含Order BY子句在内的函数非路径检查的Order实例,您可以使用JpaSort。添加可能不安全的排序。

    例:使用SortJpaSort

    public interface UserRepository extends JpaRepository<User, Long> {
    
      @Query("select u from User u where u.lastname like ?1%")
      List<User> findByAndSort(String lastname, Sort sort);
    
      @Query("select u.id, LENGTH(u.firstname) as fn_len from User u where u.lastname like ?1%")
      List<Object[]> findByAsArrayAndSort(String lastname, Sort sort);
    }
    
    repo.findByAndSort("lannister", new Sort("firstname"));               //在域模型中指向属性的有效排序表达式
    repo.findByAndSort("stark", new Sort("LENGTH(firstname)"));           //包含函数调用的无效排序。Thows 异常
    repo.findByAndSort("targaryen", JpaSort.unsafe("LENGTH(firstname)")); //包含显式不安全顺序的有效排序。
    repo.findByAsArrayAndSort("bolton", new Sort("fn_len"));              //指向别名函数的有效排序表达式。
    

    6.使用(自)命名参数

    ​ 默认情况下,Spring Data JPA使用基于位置的参数绑定,如上面的所有示例所述,即参数和?的位置一一顺序对应。这使得查询方法在重构参数位置时容易出错。要解决这个问题,可以使用@Param注释为方法参数提供一个具体名称,并在查询中绑定该名称,如下面的示例所示:

    例:使用命名参数

    public interface UserRepository extends JpaRepository<User, Long> {
    
      @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
      User findByLastnameOrFirstname(@Param("lastname") String lastname,
                                     @Param("firstname") String firstname);
    }
    

    这样子就不需要再保证位置的一一对应了,只需要保证名称的对应即可,方法参数根据它们在定义的查询中的顺序进行切换

    参考文档

    1.翻译:【JPA Query Methods】


    下一篇:【Spring JPA 更新查询-自定义删改】

  • 相关阅读:
    bug记录_signalr执行$.connnection.testhub结果为空
    mysql存储过程
    docker安装svn
    Redis在windows下安装过程
    JAVA日期查询:季度、月份、星期等时间信息
    VueX(Vue状态管理模式)
    Lambda常用写法
    Docker部署SpringBoot项目
    vue+nginx+docker 的前端项目部署方案
    docker常用操作
  • 原文地址:https://www.cnblogs.com/masterchd/p/jpa.html
Copyright © 2011-2022 走看看