2010-12-06 63 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分享我的解決方法。

相關問題