2010-12-06 44 views
20

Nous sommes actuellement construire une carte manuellement en fonction des deux champs qu'une requête nommée renvoie, car JPA fournit uniquement un getResultList().Can JPA renvoie les résultats sous forme de carte?

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

Mais je me sens comme un mappeur personnalisé ou similaire serait plus performant puisque cette liste pourrait facilement être 30,000+ résultats.

Toutes les idées pour créer une carte sans itération manuelle.

(je me sers OpenJPA, pas mise en veille prolongée)

+0

Que serait votre clé de carte? –

+0

Comme le code le montre, le champ numérique (Long), l'une des deux valeurs renvoyées. BUt Je pourrais vivre avec n'importe quel type, tant que la clé est le nombre et la valeur est le nom. J'ai ajouté la déclaration pour plus de détails. – Eddie

Répondre

0

Comment cela?

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

et

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

@zawhut - merci, mais cela renvoie encore une liste .. Le problème est que je dois utiliser les résultats dans une autre méthode et j'ai besoin d'une méthode de recherche rapide .. Je pensais qu'une carte serait la meilleure façon de le faire. – Eddie

14

Il n'y a aucun moyen standard pour obtenir JPA pour retourner une carte.

voir question connexe: JPA 2.0 native query results as map

Itération manuellement doivent être bien. Le temps d'itérer une liste/carte en mémoire va être faible par rapport au temps d'exécution/retour des résultats de la requête. Je n'essaierais pas de comprendre les règles internes ou la personnalisation de l'APP, à moins qu'il n'y ait des preuves concluantes que l'itération manuelle n'était pas réalisable. De plus, si vous avez d'autres endroits où vous placez des listes de résultats de requête dans Maps, vous voudrez probablement refactoriser cela en méthode utilitaire avec un paramètre pour indiquer la propriété de la clé de carte.

0

avec un résultat personnalisé class et un peu de goyave, ceci est mon approche qui fonctionne très bien:

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

Vous pouvez récupérer une liste de java.util. Map.Entry à la place. Par conséquent, la collection dans votre entité doit être modelée comme une carte:

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

Dans l'exemple PHONETYPE est un ENUM simple, PhoneNumber est une entité. Dans votre requête utiliser le mot-clé ENTRY qui a été introduit dans JPA 2.0 pour les opérations de carte:

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

Vous êtes maintenant prêt à récupérer les entrées et commencer à travailler avec elle:

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

Si vous avez besoin de la entrées dans une carte, mais ne veulent pas parcourir votre liste d'entrées manuellement, jetez un oeil sur ce poste Convert Set<Map.Entry<K, V>> to HashMap<K, V> qui fonctionne avec Java 8.

0

S'il vous plaît se référer, JPA 2.0 native query results as map

Dans votre cas Postgres, ce serait quelque chose comme,

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

Veuillez noter, je partage juste ma solution de contournement avec Postgres.