2010-12-06 30 views
20

我们目前正在根据名称查询返回的两个字段手动构建地图,因为JPA只提供了一个getResultList()。JPA可以将结果作为地图返回吗?

@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); 
} 

但我觉得自定义映射器或类似的会更高性能,因为这个列表可以很容易地是30,000+结果。

任何创建一个地图,而无需手动迭代的想法。

(我使用OpenJPA中,不冬眠)

+0

什么将作为您的地图钥匙吗? – 2010-12-06 22:04:12

+0

与代码显示一样,数字字段(Long)返回两个值中的一个。 BUt我可以和任何类型一起生活,只要关键是数字,价值就是名字。我添加了更多细节的声明。 – Eddie 2010-12-06 22:09:34

回答

0

这个怎么样?

@NamedNativeQueries({ 
@NamedNativeQuery(
    name="myQuery", 
    query="select c.name, c.number from Client c", 
    resultClass=RegularClient.class 
) 
}) 

 public static List<RegularClient> runMyQuery() { 
    return entityManager().createNamedQuery("myQuery").getResultList(); 
} 
14

没有标准的方式来获得JPA返回地图。

看到相关的问题:JPA 2.0 native query results as map

手动迭代应该罚款。在内存中迭代列表/映射的时间相对于执行/返回查询结果的时间要小。除非有确凿的证据表明手动迭代不可行,否则我不会尝试与JPA内部结构或定制进行对话。另外,如果您有其他地方将查询结果列表转换为地图,则可能需要使用参数将其重构为实用程序方法,以指示地图关键属性。

0

通过自定义的结果class,有点番石榴,这是我的做法,效果很好:

public static class SlugPair { 
    String canonicalSlug; 
    String slug; 

    public SlugPair(String canonicalSlug, String slug) { 
     super(); 
     this.canonicalSlug = canonicalSlug; 
     this.slug = slug; 
    } 

} 

...

final TypedQuery<SlugPair> query = em.createQuery(
    "SELECT NEW com.quikdo.core.impl.JpaPlaceRepository$SlugPair(e.canonicalSlug, e.slug) FROM " 
     + entityClass.getName() + " e WHERE e.canonicalSlug IN :canonicalSlugs", 
    SlugPair.class); 

query.setParameter("canonicalSlugs", canonicalSlugs); 

final Map<String, SlugPair> existingSlugs = 
    FluentIterable.from(query.getResultList()).uniqueIndex(
     new Function<SlugPair, String>() { 
    @Override @Nullable 
    public String apply(@Nullable SlugPair input) { 
     return input.canonicalSlug; 
    } 
}); 
4

可以检索java.util中的列表。代替Map.Entry。 因此在实体收集应建模为一个地图:

@OneToMany 
@MapKeyEnumerated(EnumType.STRING) 
public Map<PhoneType, PhoneNumber> phones; 

在这个例子中PHONETYPE是一个简单的枚举,******中国是一个实体。在查询中使用的是在JPA 2.0中引入了地图操作ENTRY关键字:

public List<Entry> getPersonPhones(){ 
    return em.createQuery("SELECT ENTRY(pn) FROM Person p JOIN p.phones pn",java.util.Map.Entry.class).getResultList(); 
} 

您现在可以检索条目并开始使用它:

List<java.util.Map.Entry> phoneEntries = personDao.getPersonPhoneNumbers(); 
for (java.util.Map.Entry<PhoneType, PhoneNumber> entry: phoneEntries){ 
    //entry.key(), entry.value() 
} 

如果您仍需要在地图中的条目,但不想手动遍历条目列表,看看这篇文章Convert Set<Map.Entry<K, V>> to HashMap<K, V>,它适用于Java 8。

0

请参考,JPA 2.0 native query results as map

在你的情况在Postgres,它会是这样的,

List<String> list = em.createNativeQuery("select cast(json_object_agg(c.number, c.name) as text) from schema.client c") 
        .getResultList(); 

//handle exception here, this is just sample 
Map map = new ObjectMapper().readValue(list.get(0), Map.class); 

请注意,我只是在Postgres分享我的解决方法。

相关问题