Может ли JPA возвращать результаты в виде карты? - PullRequest
27 голосов
/ 07 декабря 2010

В настоящее время мы строим карту вручную на основе двух полей, возвращаемых именованным запросом, поскольку 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);
}

Но я чувствую, что пользовательский сопоставитель или аналогпроизводительность, так как этот список может легко получить более 30 000 результатов.

Любые идеи по созданию карты без итерации вручную.

(я использую OpenJPA, а не спящий режим)

Ответы [ 7 ]

15 голосов
/ 20 ноября 2011

Не существует стандартного способа заставить JPA вернуть карту.

см. Связанный вопрос: Результаты собственного запроса JPA 2.0 в виде карты

Итерации вручную должны выполняться хорошо,Время итерации списка / карты в памяти будет небольшим по сравнению со временем выполнения / возврата результатов запроса.Я не стал бы пытаться возиться с внутренними компонентами или настройками JPA, если бы не было убедительных доказательств того, что ручная итерация не работала.

Кроме того, если у вас есть другие места, где вы превращаете списки результатов запроса в Карты, вы, вероятно, захотитепреобразовать его в служебный метод с параметром для указания свойства ключа карты.

8 голосов
/ 29 декабря 2015

Вы можете получить список java.util. Map.Entry .Поэтому коллекция в вашей сущности должна быть смоделирована как Map:

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

В примере PhoneType - это простое перечисление, PhoneNumber - это сущность.В своем запросе используйте ключевое слово ENTRY, которое было введено в JPA 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();
}

Теперь вы готовы получить записи и начать работать с ними:

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

Если вам все еще нужны записи на карте, но вы не хотите просматривать список записей вручную, просмотрите этот пост Преобразовать набор> к HashMap, который работает с Java 8.

4 голосов
/ 25 сентября 2018

Это прекрасно работает.
Код репозитория:

@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

0 голосов
/ 03 апреля 2019
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 голосов
/ 13 сентября 2017

Пожалуйста, обратитесь, Результаты собственного запроса 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 голосов
/ 28 ноября 2013

С пользовательским результатом class и немного Guava, это мой подход, который работает довольно хорошо:

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 голосов
/ 07 декабря 2010

Как насчет этого?

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