web-dev-qa-db-ja.com

JPAは結果をマップとして返​​すことができますか?

JPAはgetResultList()のみを提供するため、現在、名前付きクエリが返す2つのフィールドに基づいて手動でマップを構築しています。

@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を使用しています)

29
Eddie

JPAに地図を返させる標準的な方法はありません。

関連する質問を参照してください: JPA 2.0ネイティブクエリの結果をマップとして

手動での反復は問題ないはずです。メモリ内のリスト/マップを反復する時間は、クエリ結果を実行/返す時間に比べて短くなります。手動の反復が機能しないという決定的な証拠がない限り、JPAの内部構造やカスタマイズに手を加えようとはしません。

また、クエリ結果リストをマップに変換する他の場所がある場合は、マップキープロパティを示すパラメーターを使用してユーティリティメソッドにリファクタリングすることをお勧めします。

15
wrschneider

代わりに、Java.util。Map.Entryのリストを取得できます。したがって、エンティティのコレクションはマップとしてモデル化する必要があります。

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

この例のPhoneTypeは単純な列挙型で、PhoneNumberはエンティティです。クエリでは、マップ操作用に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。

8
mika

これは正常に動作します。
リポジトリコード:

@Repository
public interface BookRepository extends CrudRepository<Book,Id> {

    @Query("SELECT b.name, b.author from Book b")
    List<Object[]> findBooks();
}

service.Java

      List<Object[]> list = bookRepository.findBooks();
                for (Object[] ob : list){
                    String key = (String)ob[0];
                    String value = (String)ob[1];
}

リンク https://codereview.stackexchange.com/questions/1409/jpa-query-to-return-a-map

3
krishna Murari

これはどう ?

@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
zawhtut

JPA 2.0ネイティブクエリの結果をマップとして を参照してください

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と共有しているだけです。

0
Darshan Patel
Map<String,Object> map = null;
    try {
        EntityManager entityManager = getEntityManager();
        Query query = entityManager.createNativeQuery(sql);
            query.setHint(QueryHints.RESULT_TYPE, ResultType.Map);
        map = (Map<String,Object>) query.getSingleResult();
    }catch (Exception e){ }

 List<Map<String,Object>> list = null;
    try {
        EntityManager entityManager = getEntityManager();
        Query query = entityManager.createNativeQuery(sql);
            query.setHint(QueryHints.RESULT_TYPE, ResultType.Map);
            list = query.getResultList();
    }catch (Exception e){  }
0
Tufik Chediak

カスタム結果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;
    }
});
0
Hendy Irawan