【问题标题】:JPQL Like Case InsensitiveJPQL 不区分大小写
【发布时间】:2016-09-07 19:01:00
【问题描述】:

我想按名称不区分大小写搜索用户表中的数据。

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where lower(u.name) like %lower(?1)%")
  public List<User> findByNameFree(String name);

}

我收到一个错误:意外的令牌:%。我应该把'%'放在哪里?

【问题讨论】:

    标签: java spring jpa spring-data-jpa jpql


    【解决方案1】:

    您可以使用 concat 运算符:

    @Query("select u from User u where lower(u.name) like lower(concat('%', ?1,'%'))")
    public List<User> findByNameFree(String name);
    

    或使用命名参数:

    @Query("select u from User u where lower(u.name) like lower(concat('%', :nameToFind,'%'))")
    public List<User> findByNameFree(@Param("nameToFind") String name);
    

    (使用 Spring Boot 1.4.3 测试)

    【讨论】:

    • 好方法。谢谢!
    • 请注意,这可能会更改您的查询计划并绕过 SQL 索引,从而减慢查询速度,尤其是在表中有大量用户的情况下。这是因为它必须在每次调用时将 lower() 应用于数据库中的所有值。
    • @Max 感谢您的观察,没想到这一点。根据stackoverflow.com/questions/12855/… 的说法,有一些方法可以避免它,但这似乎很大程度上取决于您使用的数据库。
    • 当给定 null 时,宝贝!
    • nameToFind 为空时失败。有什么解决办法吗?
    【解决方案2】:

    如果这只是您想要的,并且您使用的是 Spring Data JPA,则无需编写查询。

    List<User> findByNameContainingIgnoreCase(String name);
    

    否则,您需要在将name 属性与% 包装起来,然后将其传递给方法(将它们直接放在查询中根本行不通)。或者不使用查询,而是使用规范或 Criteria API 来创建查询。

    【讨论】:

    • 我想为使用查询的一般问题找到解决方案。
    【解决方案3】:

    我使用的是 Spring Boot 2.1.6,您可以使用 Containing、Contains 和 IsContaining 定义查询方法,如下所示:

    List<User> findByNameContaining(String name);
    List<User> findByNameContains(String name);
    List<User> findByNameIsContaining(String name);
    

    不区分大小写:

    List<User> findByNameContainingIgnoreCase(String name);
    

    或者你也可以定义如下:

    @Query("select u from User u where lower(u.name) like lower(concat('%', :name,'%'))")
    public List<User> findByName(@Param("name") String name);
    

    @Param 注释在这里很重要,因为我们使用的是命名参数。

    【讨论】:

      【解决方案4】:

      不使用 concat 并使用 TypedQuery:

        TypedQuery<Baptism> query = entityManager.createQuery("SELECT d FROM " + Baptism.class.getSimpleName()
                                  + " d JOIN d.person p WHERE UPPER(p.lastName) LIKE UPPER(:ln)", Baptism.class);
                          query.setParameter("ln", "%" + ln + "%");
      

      【讨论】:

        【解决方案5】:

        您可以使用wildcard matching

        例如,我想搜索像haha 这样的名字,

        @Query("select u from User u where lower(u.name) like :u_name")
        public List<User> findByNameFree(@Param("u_name") String name);
        List<User> users = userDao.findByNameFree("%haha");
        

        【讨论】:

        • @Query("select u from User u where lower(u.name) like lower(:u_name)")
        猜你喜欢
        • 2013-03-24
        • 2012-12-01
        • 2013-03-06
        • 2020-02-18
        • 1970-01-01
        • 2020-05-25
        • 1970-01-01
        • 1970-01-01
        • 2012-02-03
        相关资源
        最近更新 更多