JPQL 查询使用 AttributeConverter 存储的列表中的项目

JPQL query for item in list stored with AttributeConverter

正如 Tobias Liefke 所建议的那样 ,我已经实现了一个 AttributeConverter 来将列表值存储到一个以逗号分隔的字符串列中。

转换器Class:

public class ListNumbersConverter implements AttributeConverter<List<Long>, String>

实体中的字段 class:

@Column(name = "user_ids", nullable = false)
@Convert(converter = ListNumbersConverter.class)
private List<Long> userIds;

它工作正常,但我无法查询特定列表项的记录。我尝试在 JPQL 查询中使用 IN 运算符,如下所示:

? in userIds 

如果输入参数是 DB 值中的第一个元素,我只得到一个结果。例如:DB 值为“1,2,3”。如果上述查询的输入参数值为 1,我可以检索此记录,但如果值为 2 或 3,则无法检索。我必须如何编写查询来检索包含特定项目的所有记录?

我的数据库是 MySQL.

Hibernate 不知道转换器如何将列表映射到列。它无法构建从 JPQL ? in userIds 到匹配的 SQL 片段的映射,因为它需要知道您的转换器是如何实现的。

但您始终可以自己构建 SQL 片段,例如:

WHERE concat(',', entity.userIds, ',') LIKE concat('%,', ?, ',%')

第一个 concat 是为了确保表达式甚至匹配列表的第一个和最后一个值(不会以分隔符开始或结束)。

可以使用其他特定于数据库的函数,但此示例适用于我所知道的所有数据库类型。

另一条评论:您不应该尝试在查询中加入 userIds - 因为它属于 basic 类型,即使它是一个列表。请参阅 @Convert:

的 JavaDoc

The Convert annotation is used to specify the conversion of a Basic field or property.

然而,如果您直接将属性与文字 (entity.userIds = '1') 进行比较,Hibernate 会报错,因为属性的类型与文字的类型不匹配。但是只要你在比较的任何一方使用像上面这样的函数,它就不会抱怨。