2010-05-26 13 views
29

¿Hay alguna forma de que pueda contar el tamaño de una colección asociada sin inicializar?Tamaño de recopilación de recuento de hibernación sin inicializar

p. Ej.

Select count(p.children) from Parent p 

(hay una buena razón por la cual no puedo hacer esto de otra manera como mi cláusula where es más complicado y mi de la cláusula es una consulta polimórfica)

Gracias.

+0

Tenga en cuenta que parece tener poco control sobre la clave utilizada cuando se realiza la comprobación de existencia con contiene en un LazyCollection. Eso es un poco complicado porque no puedes usar claves naturales para hacer la verificación de existencia. –

Respuesta

53

Una posible solución distinta de las consultas podría estar mapeando children con lazy="extra" (en notación XML). De esta forma, puede buscar a la matriz con la consulta que necesite y luego llamar al parent.getChildren().size() sin cargar toda la colección (solo se ejecuta una consulta de tipo SELECT COUNT).

Con anotaciones, sería

@OneToMany 
@org.hibernate.annotations.LazyCollection(
org.hibernate.annotations.LazyCollectionOption.EXTRA 
) 
private Set<Child> children = new HashSet<Child>(); 

Actualización: Presupuesto de Java Persistence with Hibernate, cap. 13.1.3:

Un proxy es inicializado si se llama a cualquier método que no es el método getter identificador , una colección se inicializa si se inicia la iteración a través de sus elementos o si que llamar a cualquiera de la gestión de cobro operaciones, como size() y . Hibernate proporciona una configuración adicional que es principalmente útil para colecciones grandes; se pueden mapear como extra perezosa. [...]

[asignada como el anterior,] la colección ya no se inicializa si se llama size(), o isEmpty() - la base de datos se realiza una consulta para recuperar la información necesaria. Si es un Map o un List, las operaciones containsKey() y get() también consultan la base de datos directamente.

Así que con una entidad asignada como anteriormente, a continuación, puede hacer

Parent p = // execute query to load desired parent 
// due to lazy loading, at this point p.children is a proxy object 
int count = p.getChildren().size(); // the collection is not loaded, only its size 
+0

puede elaborar un poco más sobre esto. –

+1

@Varun, mira mi actualización. –

+2

Tenga cuidado, hay un error: https://hibernate.atlassian.net/browse/HHH-9227 –

1

Usted puede utilizar Sesión # createFilter que es una forma de HQL que opera de forma explícita en las colecciones. Por ejemplo, usted menciona los padres y niños por lo que si usted tiene una persona p de la forma más básica sería:

session.createFilter(p.getChildren(), "").list() 

Esto simplemente se devuelve una lista de los niños. Es importante tener en cuenta que la colección devuelta no es "en vivo", de ninguna manera está asociada con p.

La parte interesante proviene del segundo argumento. Este es un fragmento HQL. Aquí, por ejemplo, es posible que desee:

session.createFilter(p.getChildren(), "select count(*)").uniqueResult(); 

Usted ha mencionado que tiene una cláusula en donde, por lo que también puede ser que desee:

session.createFilter(p.getChildren(), "select count(*) where this.age > 18").uniqueResult(); 

Aviso existe ninguna es de cláusula. Es decir que la cláusula from está implícita en la asociación.A los elementos de la colección se les da el alias "this" para que pueda referirse a él desde otras partes del fragmento HQL.

-2

Usted puede hacer lo mismo de esta manera:

@Override 
public FaqQuestions getFaqQuestionById(Long questionId) { 
    session = sessionFactory.openSession(); 
    tx = session.beginTransaction(); 
    FaqQuestions faqQuestions = null; 
    try { 
     faqQuestions = (FaqQuestions) session.get(FaqQuestions.class, 
       questionId); 
     Hibernate.initialize(faqQuestions.getFaqAnswers()); 

     tx.commit(); 
     faqQuestions.getFaqAnswers().size(); 
    } finally { 
     session.close(); 
    } 
    return faqQuestions; 
} 

sólo tiene que utilizar faqQuestions.getFaqAnswers() size() nin su controlador y obtendrá el tamaño si la lista perezosamente intialised, sin recuperar ni la propia lista..

+1

¿Qué sucede exactamente aquí y por qué debería funcionar? ¿Por qué comprometer la transacción? – h22

Cuestiones relacionadas