正如Tobias Liefke建议here,我已经实现了AttributeConverter
来将列表值存储到以逗号分隔的单个字符串列中。
转换器类:
public class ListNumbersConverter implements AttributeConverter<List<Long>, String>
实体类中的字段:
@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则无法检索。如何编写查询以检索包含特定项目的所有记录?< / p>
我的数据库是MySQL。
答案 0 :(得分:0)
Hibernate并不知道 转换器如何将列表映射到列。它无法构建从JPQL ? in userIds
到匹配的SQL片段的映射,因为它需要知道如何实现转换器。
但是你总是可以自己构建那个SQL片段,例如:
WHERE concat(',', entity.userIds, ',') LIKE concat('%,', ?, ',%')
第一个concat
是确保表达式甚至匹配列表的第一个和最后一个值(不会以分隔符开头或结尾)。
可以使用其他特定于数据库的函数,但此示例适用于我所知道的所有数据库类型。
另一个评论:您不应该尝试在查询中加入userIds
- 因为它是基本类型,即使它是一个列表。请参阅@Convert
的JavaDoc:
转换注释用于指定基本字段或的转换 属性。
然而,如果您将属性直接与文字(entity.userIds = '1'
)进行比较,Hibernate会抱怨,因为属性的类型与文字的类型不匹配。但只要您在比较的任何一方使用上述功能,它就不会抱怨。