JPQL忽略大小写的Like查询

69

我想按照姓名不区分大小写的方式在用户表中搜索数据。

@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);

}

我收到一个错误消息:unexpected token: %。我应该把“%”放在哪里?

7个回答

145

您可以使用连接运算符:

@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测试)


好的方法。谢谢! - Saxophonist
请注意,这可能会更改您的查询计划并绕过SQL索引,从而减慢查询速度,特别是在表中有大量用户时。这是因为它必须在每次调用时将lower()应用于数据库中的所有值。 - Max
@Max 谢谢你的观察,我没有想到。根据 https://dev59.com/qEXRa4cB1Zd3GeqPoADU 上的说法,有一些方法可以避免这种情况,但似乎很大程度上取决于你使用的数据库。 - Wim Deblauwe
当给定 null 时,嘭! - withoutOne
当nameToFind为空时,它会失败。有什么解决方案吗? - Malindu Sandaruwan
@MalinduSandaruwan 这是因为你需要指定当 nameToFind 为空时想要发生什么。如果你不想按名称过滤,则必须从字符串中省略整个子句 lower(u.name) like lower(...)。如果你有多个子句,你将不得不省略并且使用 1=1 替换省略部分的 and。以此类推。 - Tobia

41

如果这正是你想要的,而且你正在使用Spring Data JPA,那么你不需要编写查询。

List<User> findByNameContainingIgnoreCase(String name);
Else 你需要在将name属性传递给该方法之前,使用%将其包装起来(直接放入查询中将不起作用)。或者不使用查询,而是使用规范或Criteria API来创建查询。

1
我想找到一个使用查询的通用问题解决方案。 - windupurnomo
无法工作... 值未转换为小写 - storm_buster

16

我正在使用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注释很重要,因为我们正在使用一个命名参数。


拼接的结果是“%name%”作为搜索词吗?百分号的作用是什么? - undefined

3
不使用concat并使用TypedQuery:
不使用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 + "%");

0

如何在此查询中添加忽略大小写:

@Query("SELECT p FROM Product p WHERE CONCAT(p.name, ' ', p.brand, ' ', p.madein, ' ', p.price) LIKE %?1%")

我尝试使用 -

findProductContainingIgnoreCase(String keyword)

@Query("SELECT p FROM Product p WHERE CONCAT(lower(p.name), ' ', lower(p.brand), ' ', lower(p.madein), ' ', lower(p.price)) LIKE %?1%")

欢迎任何建议。


0
你可以使用Spring Boot的命名约定策略来实现按照命名模式查找,例如:findBy你的字段驼峰命名LikeIgnoreCase。
例如:findByUserNameLikeIgnoreCase(userName: String): List<UserEntity>

-1

您可以使用通配符匹配。

例如,我想搜索类似于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");

4
@Query("select u from User u where lower(u.name) like lower(:u_name)") 的翻译如下:查询名字中包含指定字符串(不区分大小写)的用户,语句为:@Query("select u from User u where lower(u.name) like lower(:u_name)")。 - ekem chitsiga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接