2011-01-11 26 views
5

estoy usando JPA2/hibernación con este modelo de datos:¿Cómo puedo recuperar múltiples objetos con JPA?

class Stock { 
    @ManyToOne 
    private StockGroup stockGroup; 
    private boolean visible; 
} 
class StockGroup { 
    @OneToMany(mappedBy = "stockGroup") 
    private List<Stock> stocks; 
} 

me gustaría recuperar de donde visible==true que contiene de StockGroup archivo.
se me ha ocurrido con este código defectuoso:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<StockGroup> q = cb.createQuery(StockGroup.class); 
Root<StockGroup> r = q.from(StockGroup.class); 
Join<StockGroup, Stock> j = r.join(StockGroup_.stocks, JoinType.INNER); 
Predicate p = cb.equal(j.get(Stock_.visible), true); 

// This becomes a cartesian product :(
List<StockGroup> l = em.createQuery(q.where(p)).getResultList(); 
// Stocks are not filtered on visible :(
l.get(0).getStocks(); 

¿Es posible recuperar los objetos y StockGroup archivo con uno o CriteriaQuery puede JPA llenar solamente un tipo a la vez? ¿O puedo agregar algunos criterios cuando .getStocks() se llena de forma perezosa?

Respuesta

8

El truco para hacer esto está devolviendo una tupla que contiene una anticuada unión entre la Bolsa y el StockGroup, así:

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Tuple> q = cb.createQuery(Tuple.class); 
Root<Stock> sRoot = q.from(Stock.class); 
Root<StockGroup> sgRoot = q.from(StockGroup.class); 

q.select(cb.tuple(sRoot, sgRoot)).where(
    cb.and(cb.equal(sRoot.get(Stock_.stockGroup), sgRoot), 
     cb.isTrue(sRoot.get(Stock_.visible)))); 
List<Tuple> l = em.createQuery(q).getResultList(); 

La tupla no es entonces escribir totalmente seguro, pero se puede llegar a ella por la posición (o por alias, si usted ha dado su selecto expresiones o raíces de un alias):

for (Tuple t : l) { 
    Stock s = (Stock) t.get(0); 
    StockGroup sg = (StockGroup) t.get(1); 

    System.out.println("Stock is : " + s + " .... StockGroup: " + sg); 
} 

Hay una good article on IBM DeveloperWorks on JPA2 Typesafe Queries.

¡Buena suerte en sus esfuerzos de JPA2!

+0

Si tuviera miedo de esto ... uniones manuales, moldes inseguros, sintaxis veb y armar manualmente los objetos. Tal vez deba cambiar a algo como OpenJPA o Querydsl. Pero aún así, usted respondió mi pregunta perfectamente (he leído el artículo enitre). La bonificación le indica si responde la segunda parte: ¿Qué sucede si primero solo recupero StockGroups, puedo agregar algunos Criterios cuando se llame a .getStocks()? En otras palabras, ¿puedo meterme con el objeto proxy? – Cojones

+0

No creo que sea compatible con JPA: ¿dónde está esa construcción (colecciones filtradas), ya que obtendría una colección incompleta en su objeto? Tampoco veo cómo OpenJPA lo ayudaría, y no sé lo suficiente sobre QueryDsl para ofrecer consejos. ¡Lo siento! – JesperSM

+0

Sin embargo, podría agregar algunos métodos/ayudantes de alto nivel para hacer la unión manual, como manualJoin (cb, sgRoot, sRoot, Stock_.group, cb.isTrue (sRoot.get (Stock_.visible)) y tal vez envolver la lista de tuplas en consecuencia, como una curita de tipo? Es una pena que no hicieron Tuple1 , Tuple2 , etc. – JesperSM

Cuestiones relacionadas