Edd*_*die 32 jpa resultset map openjpa
我们目前基于命名查询返回的两个字段手动构建映射,因为JPA仅提供getResultList().
@NamedQuery{name="myQuery",query="select c.name, c.number from Client c"}
HashMap<Long,String> myMap = new HashMap<Long,String>();
for(Client c: em.createNamedQuery("myQuery").getResultList() ){
myMap.put(c.getNumber, c.getName);
}
Run Code Online (Sandbox Code Playgroud)
但是我觉得自定义映射器或者类似物会更高效,因为这个列表很容易就会产生30,000多个结果.
任何想法,无需手动迭代即可构建Map.
(我使用的是OpenJPA,而不是休眠)
Vla*_*cea 32
从 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()
)
);
Run Code Online (Sandbox Code Playgroud)
如果您使用的是 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()
)
);
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用MapResultTransformerHibernate 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();
Run Code Online (Sandbox Code Playgroud)
该MapResultTransformer适用于项目的Java 6的仍在运行或使用旧版本的Hibernate。
OP 说:
但是,我觉得自定义映射器或类似的会更高效,因为此列表很容易包含 30,000 多个结果。
这是一个可怕的想法。您永远不需要选择 30k 条记录。这将如何适应用户界面?或者,为什么要对如此大量的记录进行操作?
您应该使用查询分页,因为这将帮助您减少事务响应时间并提供更好的并发性。
wrs*_*der 15
没有标准的方法让JPA返回地图.
查看相关问题:JPA 2.0本机查询结果为map
手动迭代应该没问题.相对于执行/返回查询结果的时间,在内存中迭代列表/映射的时间将变得很小.除非有确凿的证据表明手动迭代不可行,否则我不会尝试使用JPA内部或定制.
此外,如果您有其他地方将查询结果列表转换为地图,您可能希望将其重构为带有参数的实用程序方法,以指示地图键属性.
您可以检索java.util的列表.而是Map.Entry.因此,您实体中的集合应建模为地图:
@OneToMany
@MapKeyEnumerated(EnumType.STRING)
public Map<PhoneType, PhoneNumber> phones;
Run Code Online (Sandbox Code Playgroud)
在示例中,PhoneType是一个简单的枚举,PhoneNumber是一个实体.在您的查询中,使用ENTRYJPA 2.0中为地图操作引入的关键字:
public List<Entry> getPersonPhones(){
return em.createQuery("SELECT ENTRY(pn) FROM Person p JOIN p.phones pn",java.util.Map.Entry.class).getResultList();
}
Run Code Online (Sandbox Code Playgroud)
您现在可以检索条目并开始使用它:
List<java.util.Map.Entry> phoneEntries = personDao.getPersonPhoneNumbers();
for (java.util.Map.Entry<PhoneType, PhoneNumber> entry: phoneEntries){
//entry.key(), entry.value()
}
Run Code Online (Sandbox Code Playgroud)
如果您仍然需要条目的地图,但不希望通过您的手动条目列表进行迭代,对这个帖子看看转换集<Map.Entry的<K,V >>到的HashMap <K,V>其中工程用Java 8.
这工作正常。
存储库代码:
@Repository
public interface BookRepository extends CrudRepository<Book,Id> {
@Query("SELECT b.name, b.author from Book b")
List<Object[]> findBooks();
}
Run Code Online (Sandbox Code Playgroud)
服务.java
List<Object[]> list = bookRepository.findBooks();
for (Object[] ob : list){
String key = (String)ob[0];
String value = (String)ob[1];
}
Run Code Online (Sandbox Code Playgroud)
链接https://codereview.stackexchange.com/questions/1409/jpa-query-to-return-a-map
zaw*_*tut -2
这个怎么样 ?
@NamedNativeQueries({
@NamedNativeQuery(
name="myQuery",
query="select c.name, c.number from Client c",
resultClass=RegularClient.class
)
})
Run Code Online (Sandbox Code Playgroud)
和
public static List<RegularClient> runMyQuery() {
return entityManager().createNamedQuery("myQuery").getResultList();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
67580 次 |
| 最近记录: |