如何按照标识符或主键的顺序加载多个Hibernate实体

问题描述 投票:1回答:2

我们如何使用提供给Hibernate查询的Pks列表的顺序使用Hibernate加载多个实体?

在下面的代码中,列表输出的顺序是升序,而不是参数中提供Pks的顺序

Criteria criteria = s.createCriteria(entityClass).add(Restrictions.in(idPropertyName, pks));

List list = criteria.list();
java hibernate sql-order-by entity identifier
2个回答
0
投票

获得它们,然后使用比较器对它们进行排序,该比较器比较列表中每个实体的索引。

例如:

Map<Long, Integer> indexById = new HashMap<>();
for (int i = 0; i < pks.size(); i++) {
    indexById.put(pks.get(i), i);
}

List<MyEntity> entities = seachByIds(pks);

entities.sort(Comparator.comparing(entity -> indexById.get(entity.getId())));

0
投票

正如我在this article中所解释的,有几种方法可以实现此目标。

在您的示例中,您使用的是传统的Hibernate Criteria,但由于自Hibernate 4起已不推荐使用,因此很可能在Hibernate 6中将其删除。

因此,最好使用以下替代方法之一。

[请注意,在您的示例中,您具有在pks类型的List变量中定义的实体标识符值,并且我还将在以下示例中重复使用它。

JPQL

您可以使用如下所示的JPQL查询:

List<Book> books = entityManager
.createQuery(
    "select b " +
    "from Book b " +
    "where b.id in (:ids)", Book.class)
.setParameter("ids", pks)
.getResultList();

[使用JPQL时,ids参数将按照在pks变量中定义的顺序传递实体标识符。

标准API

如果要动态构建查询,则可以使用Criteria API查询:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Book> query = builder.createQuery(Book.class);

ParameterExpression<List> ids = builder.parameter(List.class);

Root<Book> root = query
.from(Book.class);

query
.where(
    root.get("id").in(
        ids
    )
);

List<Book> books = entityManager
.createQuery(query)
.setParameter(ids, pks)
.getResultList();

[使用Criteria API时,ids参数将按照在pks变量中定义的顺序传递实体标识符。

特定于休眠的multiLoad

List<Book> books = entityManager
.unwrap(Session.class)
.byMultipleIds(Book.class)
.multiLoad(pks);

默认情况下,休眠multiLoadids参数将按照在pks变量中定义的顺序传递实体标识符。仅当您显式调用enableOrderedReturn(false)时,结果集才会排序。

现在,JPQL和Criteria API也可以从hibernate.query.in_clause_parameter_padding optimization中受益,这使您可以增加SQL语句缓存机制。

有关通过标识符加载多个实体的更多详细信息,请检出hibernate.query.in_clause_parameter_padding

© www.soinside.com 2019 - 2024. All rights reserved.