2010-12-06 24 views
20

JPAはgetResultList()のみを提供しているので、現在、名前付きクエリが返す2つのフィールドに基づいてマップを手動で構築しています。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); 
} 

しかし、このリストは3万以上の結果になる可能性があるため、カスタムマッパーや類似のものがより効果的であるように感じます。

マップを手動で反復せずに作成するためのアイデア。

この程度

+0

マップキーとしてはどのようなものが使用されますか? –

+0

コード表示と同様に、数値フィールド(Long)、2つの値のいずれかが返されます。私は任意のタイプで生きることができますが、キーが数値であり、値が名前である限り。私は詳細については宣言を追加しました。 – Eddie

答えて

0

どのように(私はOpenJPAのではなく、休止状態を使用していますか)?

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

@ zawhut - ありがとうございますが、これでもまだリストが返されます。 問題は、別のメソッド内で結果を使用する必要があり、高速検索メソッドが必要なことです。 – Eddie

14

JPAは、マップを返すために取得するための標準的な方法はありません。

は、関連する質問を参照してください。手動で反復処理JPA 2.0 native query results as map

は問題ないはずです。メモリ内のリスト/マップを反復する時間は、クエリ結果を実行/返す時間に対して相対的に小さくなります。手作業による反復が不可能であるという決定的な証拠がない限り、私はJPAの内部構造またはカスタマイズを行うつもりはありません。

また、クエリ結果リストをマップに変換する場所が他にある場合は、マップキープロパティを示すパラメータを持つユーティリティメソッドにリファクタリングする必要があります。カスタム結果classとグアバのビットで

0

、これは非常にうまく機能し、私のアプローチです:

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は単純列挙型で、PhoneNumberのが実体です。あなたは今のエントリを取得し、それを作業を開始する準備ができている

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

:あなたのクエリでは、マップ操作のためにJPA 2.0で導入されたENTRYキーワードを使用

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

あなたがまだ必要な場合マップ内のエントリは手動でエントリのリストを反復したくない場合は、Java 8で動作するこの記事Convert Set<Map.Entry<K, V>> to HashMap<K, V>を見てください。

0

Postgresにあなたのケースでは、JPA 2.0 native query results as map

を参照してください、何かのように、

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のと私の回避策を共有しています、注意してくださいだろう。

関連する問題