使用 Hibernate 执行“IN”查询

Posted

技术标签:

【中文标题】使用 Hibernate 执行“IN”查询【英文标题】:Doing an "IN" query with Hibernate 【发布时间】:2011-03-08 18:27:54 【问题描述】:

我有一个字符串中的 ID 列表,并希望使用 Hibernate 来获取具有这些 ID 的行。 TrackedItem 是一个 Hibernate/JPA 实体(对不起,如果我在这里混淆了命名)。

我的代码是:

String idsText = "380, 382, 386";
ArrayList<Long> ids = new ArrayList<Long>();

for (String i : idsText.split(","))

    ids.add(Long.getLong(i));


List<TrackedItem> items = TrackedItem.find("id IN (?)", ids).fetch();

但这失败了: JPAQueryException occured : Error while executing query from models.TrackedItem where id IN (?): java.util.ArrayList cannot be cast to java.lang.Long

如何使IN 部分工作?谢谢。

【问题讨论】:

Long.getLong(i) 不会像您认为的那样做。请改用Long.parseLong(i)。见***.com/questions/7376857/… 【参考方案1】:

您的 JPQL 查询的语法不正确。使用(带有位置参数):

List<Long> ids = Arrays.asList(380L, 382L, 386L);
Query query = em.createQuery("FROM TrackedItem item WHERE item.id IN (?1)");
query.setParameterList(1, ids)
List<TrackedItem> items = query.getResultList();

或者(带有命名参数):

List<Long> ids = Arrays.asList(380L, 382L, 386L);
Query query = em.createQuery("FROM TrackedItem item WHERE item.id IN :ids");
query.setParameterList("ids", ids)
List<TrackedItem> items = query.getResultList();

下面是JPA 1.0规范中关于参数的相关章节:

4.6.4.1 位置参数

以下规则适用于位置参数。

输入参数由问号 (?) 前缀后跟一个整数指定。例如:?1。 输入参数从 1 开始编号。请注意,同一参数可以在查询字符串中多次使用,并且查询字符串中参数的使用顺序不必符合位置参数的顺序。

4.6.4.2 命名参数

命名参数是以“:”符号为前缀的标识符。它遵循第 4.4.1 节中定义的标识符规则。命名参数区分大小写。

例子:

SELECT c
FROM Customer c
WHERE c.status = :stat

第 3.6.1 节描述了用于绑定命名查询参数的 API

【讨论】:

ids列表应该设置为,query.setParameterList("ids", idsList);不是 query.setParameter("ids", ids) 如何将String[] array1设置为查询参数 在我的情况下,我必须使用 setParameterList 和 Type 参数才能使其工作:.setParameterList("ids", ids, BigIntegerType.INSTANCE)【参考方案2】:

如果您不幸使用较旧的非 JPA 休眠,这应该适合您:

Query query = session.createQuery("FROM TrackedItem item WHERE item.id IN (:items)");
query.setParameterList("items", Arrays.asList(380L, 382L, 386L));

@SuppressWarnings("unchecked")
List<TrackedItem> results = query.list();

【讨论】:

不走运?年纪大了? o_O Bare Hibernate 与 JPA 相比具有更多功能(例如,参见 Aleksandar Radulović 的回答)。此外,您的答案似乎与已接受的答案重复.. 当时我写了这个裸休眠所需的 xml 映射与注释。此外,对接受的答案进行了编辑以匹配我的答案。多年来,很多事情都会发生变化。 Bare Hibernate 在您回答之前几年就有注释:) 但这与答案并不矛盾(仅与您的最后评论)。我只是不明白如何将 XML 映射视为“不幸的方式”,因为它更灵活、更简洁。顺便说一句,自第一个版本以来,接受的答案并没有太大变化 - 方法的名称是错误的,但值得评论。 好吧,我添加这个答案的主要原因是为了更正错误的方法名称,但即使在接受的答案中已修复,我认为展示如何使用休眠 api 获取此列表仍然很有用.也许稍微如此,但 query.getResultList() 与 query.list() 仍然有帮助。如果自 2015 年以来发生了变化,我将继续删除我的答案。【参考方案3】:

即使您的查询正确执行,如果您的查询参数包含太多值,您也可能会遇到错误。

如果您使用的是 Hibernate 5.1 或更新版本,一个可能的解决方案是使用 Session.byMultipleIds()。

session
    .byMultipleIds(TrackedItem.class)
    .multiLoad(1L, 2L, 3L);

欲了解更多信息,请参阅https://thoughts-on-java.org/fetch-multiple-entities-id-hibernate/

【讨论】:

以上是关于使用 Hibernate 执行“IN”查询的主要内容,如果未能解决你的问题,请参考以下文章

websphere启动报/WEB-INF/applicationContext-orm- hibernate.xml]: Could not resolve placeholder 'hibe

Hibernate SQL In 子句使 CPU 使用率达到 100%

使用 Hibernate 搜索的高级搜索

面试之hibernate 和mybatis

Hibernate开发流程

Hibernate:在子选择查询中使用 IN 子句时出现错误