2012-10-08 31 views
10

Digamos que Item y Bid son entidades: un Item tiene muchas ofertas. Ellos son mapeados en Hibernate en una típica relación de padre/hijo:Criterios de recolección fetch-joined ansiosos para evitar n + 1 selecciona

<class name="Item" table="ITEM"> 
    ... 
    <set name="bids" inverse="true"> 
    <key column="ITEM_ID"/> 
    <one-to-many class="Bid"/> 
    </set> 
</class> 

¿Cómo puedo evitar el n + 1 le permite elegir cuando se trata de acceder a las ofertas de cada artículo después de ejecutar esta consulta?

List<Item> items = session.createCriteria(Item.class) 
         .createAlias("bids", "b"). 
         .add(Restrictions.gt("b.amount", 100)). 
         .list(); 

Nota necesito un ansiosos ir a buscar a licitación, pero con una restricción adicional a la colección (b.amount> 100)

He intentado, sin éxito, la siguiente:

List<Item> items = session.createCriteria(Item.class) 
         .setFetchMode("bids", FetchMode.JOIN). 
         .createAlias("bids", "b"). 
         .add(Restrictions.gt("b.amount", 100)). 
         .list();       

List<Item> items = session.createCriteria(Item.class) 
         .createCriteria("bids") 
         .add(Restrictions.gt("amount", 100)). 
         .list();       
+0

http://stackoverflow.com/questions/617145/hibernate-fetching-strategy-when-to-use-join-and-when-to-use-select Creo que se lo preguntan antes ... –

Respuesta

6

Esta es una explicación de por qué la adición de una restricción a la colección de búsqueda hacia unió hace que la colección no se ha inicializado (nota que la misma consulta sin la restricción producir Traiga un ávido de la colección):

"Si tiene una relación 1: n entre las tablas A y B, y agrega una restricción a B y desea buscar A y B con entusiasmo, la pregunta sería qué sucede cuando desea navegar de A a B B. Debería solo ver los datos en B que coinciden con la restricción, o debería ver todos los Bs que están relacionados ¿A A? see more here ...

Sin embargo, utilizando HQL en lugar de criterios, ir a buscar parcialmente las colecciones licitaciones

List<Item> items = session.createQuery(
      "from Item i left join fetch i.bids b where b.amount > :amount") 
      .setParameter("amount", 100) 
      .list(); 

Me parece una contradicción, pero es la forma en que esto funciona

Por cierto, si lo que necesita es la lista de padres y todos sus hijos, pero solo los padres cuyos hijos cumplen con cierta restricción, por lo que puede usar este

List<Item> items = session.createQuery(
      "from Item i left join fetch i.bids b " + 
      "where not exists (from Bid b where b.item = i and b.amount <= :amount)") 
      .setParameter("amount", 100) 
      .list(); 

Este es un mensaje relacionado: Hibernate query not returning full object.

9

Esta consulta de criterios parece correcta:

List<Item> items = session.createCriteria(Item.class) 
        .setFetchMode("bids", FetchMode.JOIN) 
        .createAlias("bids", "b") 
        .add(Restrictions.gt("b.amount", 100)) 
        .list(); 

FetchMode.JOIN es destinado a resolver el problema n+1. ¿Ha definido alguna default_batch_fetch_size | batch-size en cualquier lugar de la asignación o configuración, que tiene un impacto inverso?

Si no es así, ¿puedes intentarlo por debajo de HQL y ver que esto resuelve tu problema?

Query query = 
     session.createQuery("from Item it left join it.bids b where b.amount=:bids"); 
query.setParamter(bids, 100); 
List<Item> items = query.list(); 
1

Creo que lo que necesita es un Criterio que utiliza Subquery Existe en otro Criterio.Una respuesta similar está aquí: https://stackoverflow.com/a/15768089/1469525

DetachedCriteria criteria = session.createCriteria(Item.class, "i"); 
criteria.setFetchMode("bids", FetchMode.JOIN); 

DetachedCriteria bidCriteria = DetachedCriteria.forClass(Bid.class, "b"); 
bidCriteria.add(Restrictions.gt("amount", 100)); 
bidCriteria.add(Restrictions.eqProperty("b.itemId", "i.id")); 
criteria.add(Subqueries.exists(bidCriteria.setProjection(Projections.property("b.id")))); 
Cuestiones relacionadas