使用 JPA Query getResultStream 返回 Map 结果
从 JPA 2.2 版本开始,您可以使用该getResultStream
Query
方法将List<Tuple>
结果转换为Map<Integer, Integer>
:
Map<Integer, Integer> postCountByYearMap = entityManager.createQuery("""
select
YEAR(p.createdOn) as year,
count(p) as postCount
from
Post p
group by
YEAR(p.createdOn)
""", Tuple.class)
.getResultStream()
.collect(
Collectors.toMap(
tuple -> ((Number) tuple.get("year")).intValue(),
tuple -> ((Number) tuple.get("postCount")).intValue()
)
);
使用 JPA Query getResultList 和 Java 流返回 Map 结果
如果您使用的是 JPA 2.1 或更早版本,但您的应用程序在 Java 8 或更高版本上运行,那么您可以使用getResultList
并将其转换List<Tuple>
为 Java 8 流:
Map<Integer, Integer> postCountByYearMap = entityManager.createQuery("""
select
YEAR(p.createdOn) as year,
count(p) as postCount
from
Post p
group by
YEAR(p.createdOn)
""", Tuple.class)
.getResultList()
.stream()
.collect(
Collectors.toMap(
tuple -> ((Number) tuple.get("year")).intValue(),
tuple -> ((Number) tuple.get("postCount")).intValue()
)
);
使用特定于 Hibernate 的 ResultTransformer 返回 Map 结果
另一种选择是使用MapResultTransformer
Hibernate Types 开源项目提供的类:
Map<Number, Number> postCountByYearMap = (Map<Number, Number>) entityManager.createQuery("""
select
YEAR(p.createdOn) as year,
count(p) as postCount
from
Post p
group by
YEAR(p.createdOn)
""")
.unwrap(org.hibernate.query.Query.class)
.setResultTransformer(
new MapResultTransformer<Number, Number>()
)
.getSingleResult();
MapResultTransformer
适用于仍在 Java 6 上运行或使用旧 Hibernate 版本的项目。
避免返回大型结果集
OP说:
但是,我觉得自定义映射器或类似的会更高效,因为这个列表很容易有 30,000 多个结果。
这是一个可怕的想法。您永远不需要选择 30k 条记录。这将如何适应 UI?或者,为什么要对这么大批量的记录进行操作?
您应该使用查询分页,因为这将帮助您减少事务响应时间并提供更好的并发性。