[英]Query resulting into "ERROR: operator does not exist: character varying ~~ bytea"
我有一个查询,我需要首先检查输入参数是否为空或比较列值以传递输入参数。 这意味着列值可以为 null 或传递指定的条件(?3 is null or cd.name like %?3%) 。
public interface PageableCategoryRepository extends PagingAndSortingRepository<Category, Long> {
@Query(
value = "select distinct c from Category c left join fetch c.descriptions cd join fetch cd.language cdl join fetch c.merchantStore cm"
+ " where cm.id=?1 and cdl.id=?2 and (?3 is null or cd.name like %?3%) order by c.lineage, c.sortOrder asc",
countQuery = "select count(c) from Category c join c.descriptions cd join c.merchantStore cm "
+ "where cm.id=?1 and cd.language.id=?2 and (?3 is null or cd.name like %?3%)")
Page<Category> listByStore(Integer storeId, Integer languageId, String name, Pageable pageable);
}
上述查询因name属性中传递的空值而失败。 错误:
错误:运算符不存在:字符变化 ~~ bytea 提示:没有运算符匹配给定的名称和参数类型。 您可能需要添加显式类型转换。 职位:3259
我试图在谷歌以及 Stack Overflow 上搜索。 有许多类似的问题被问及回答。 但是这些解决方案都不适合我。
如果有人能提供一些见解或方向,我将不胜感激。
注意:Spring boot 版本 - 2.2.7.RELEASE,使用的 Postgresql 库版本 - 42.2.16,使用的 Postgresql 版本 - 12.4
如果参数为null
,则 Postgres 无法确定参数的类型。
这里已经讨论过这个问题: Spring Data Rest: "Date is null" query throws an postgres exception
建议的解决方案是显式转换参数(如错误消息中也建议的那样),或将参数包装在coalesce
语句中。 所以这应该是诀窍:替换所有这些:
?3 is null
通过这个声明:
coalesce(?3, null) is null
当涉及参数变化的查询时,查看 Criteria API 而不是使用@Query
也是一个好主意,因为它允许非常动态地创建查询: https : @Query
标准查询
最简单的解决方案是使用显式类型转换。 此外, LIKE
的正确参数必须是字符串,因此用单引号括起来:
WHERE ... (?3::text IS NULL
OR cd.name::text LIKE '%' || ?3::text || '%'
)
如果您有可能在本机查询中使用空值,那么您必须直接使用 JPA 接口,而不是让 Spring 为您调用它们。 代替:
@Query(
value = "select distinct c from Category c left join fetch c.descriptions cd join fetch cd.language cdl join fetch c.merchantStore cm"
+ " where cm.id=?1 and cdl.id=?2 and (?3 is null or cd.name like %?3%) order by c.lineage, c.sortOrder asc",
countQuery = "select count(c) from Category c join c.descriptions cd join c.merchantStore cm "
+ "where cm.id=?1 and cd.language.id=?2 and (?3 is null or cd.name like %?3%)")
Page<Category> listByStore(Integer storeId, Integer languageId, String name, Pageable pageable);
你需要:
Page<Category> listByStore(Integer storeId, Integer languageId, String name, Pageable pageable) {
EntityManager em = ...get from somewhere (maybe parameter?);
TypedQuery<Category> q = (TypedQuery<Category>) em.createNativeQuery(..., Category.class);
Integer exampleInt = 0;
String exampleString = "";
q.setParameter(1, exampleInt).setParameter(1, storeId);
q.setParameter(2, exampleInt).setParameter(2, languageId);
q.setParameter(3, exampleString).setParameter(3, name);
}
第一次调用setParameter
告诉它类型,第二次调用setParameter
实际值。
这背后的原因是 Postgres 在解析时确定类型,而 Hibernate 无法确定null
的类型,因此在一个阶段假设它是java.io.Serializable
,然后告诉它在某个阶段假设bite[]
后期。 这样做是出于与其他数据库的遗留兼容性原因,并且不太可能改变。 也许新的 Hibernate 6.0 类型系统会解决这个问题,但我没有跟上。 因此,当它告诉 Postgres 类型是bytea
,查询解析器找不到在 bytea 和给定的其他数据库类型之间注册的隐式类型转换器,因此会引发错误。
似乎使用命名参数而不是匿名参数使其工作。
就我而言,这不起作用:
@Query("""
SELECT p FROM Participant p
WHERE (?1 IS NULL OR p.firstName LIKE ?1)
AND ?2 IS NULL OR e.id = ?2
AND p.waitingList = ?3
""")
List<Participant> findFiltered(String searchCriteria, Long eventId, boolean waitingList);
2021-07-05 10:13:39.768 WARN 28896 --- [XNIO-1 task-3] ohengine.jdbc.spi.SqlExceptionHelper:SQL 错误:0,SQLState:42883 2021-07-05 10:168:39。 28896 --- [XNIO-1 task-3] ohengine.jdbc.spi.SqlExceptionHelper:错误:运算符不存在:文本~~ bytea 提示:没有运算符匹配给定的名称和参数类型。 您可能需要添加显式类型转换。 职位 : 951
但是使用命名参数,它可以工作:
@Query("""
SELECT p FROM Participant p
WHERE (:searchCriteria IS NULL OR p.firstName LIKE :searchCriteria)
AND :eventId IS NULL OR e.id = :eventId
AND p.waitingList = :waitingList
""")
List<Participant> findFiltered(@Param("searchCriteria") String searchCriteria, @Param("eventId") Long eventId, @Param("waitingList") boolean waitingList);
否则,如错误消息所述,显式转换也可以正常工作:
@Query("""
SELECT p FROM Participant p
WHERE (cast(?1 as text) IS NULL OR p.firstName LIKE cast(?1 as text))
AND cast(?2 as long) IS NULL OR e.id = cast(?2 as long)
AND p.waitingList = ?3
""")
List<Participant> findFiltered(String searchCriteria, Long eventId, boolean waitingList);
对于可用的转换类型,请参阅https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#basic-provided
我使用 PostgreSQL 13。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.