2011-10-25 17 views
9

¿Hay alguna forma de limitar el tamaño de la lista de la relación @OneToMany en JPA? Aquí está mi ejemplo de código:@OneToMany límite de tamaño de lista de asignación

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST) 
private List<Comment> commentList; 

estoy usando EclipseLink 2,3 implementación de JPA. Gracias de antemano.

+0

posible duplicado de [Uso de anotaciones En JPA puedo limitar los registros secundarios con una cláusula where?] (Http://stackoverflow.com/questions/5857936/using-annotations-in-jpa-can-i-limit-child -records-with-a-where-clause) –

+0

Esta publicación quiere restringir la cantidad de elementos que se conservan, mientras que la vinculada quiere recuperar los elementos que también tienen otros criterios. En consecuencia, no es un "duplicado exacto". – DataNucleus

Respuesta

12

parte de la especificación Bean Validation (JSR-303) es el @Size(min=, max=) anotación:

tipos soportados son cuerdas, Colección, mapa y matrices. Compruebe si el tamaño del elemento anotado está entre min y max (inclusive).

Puede validar la colección.

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST) 
@Size(min=1, max=10) 
private List<Comment> commentList; 
2

No se puede hacer esto en la APP y que no tiene sentido porque las asignaciones están diseñados para reflejar la realidad de cuántos objetos hay en la relación.

¿Lo está haciendo por su rendimiento? Si es así lo que puede hacer es usar un Lazy traiga estilo y utilizar el BATCHSIZE anotación a cuántos específica que se desea obtener una vez:

* corrección: @Batchsize es una función de hibernación

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST, fetch=LAZY) 
@BatchSize(size=16) 
private List<Comment> commentList; 

Luego, en su código, simplemente solo itere/bucle hasta donde desee en esta colección mapeada.

De cualquier forma, desde mi experiencia las asignaciones de "hackeo" para las que se diseñan Criterias/Querys no son un esfuerzo fructífero, cuando se necesita más control o ajuste de rendimiento que @OneToMany explícitamente, la mejor manera podría ser solo hacer una consulta.

+0

Debería aclarar a qué se refería con "límite", mi respuesta se refiere a imitar el LÍMITE SQL. Si, por el contrario, desea validar el tamaño, utilice la anotación Tamaño según la respuesta de @jeha. –

+0

¿Es este Batchsize de Hibernate? – pringlesinn

+0

Podría ser, yo uso ambos, así que podría haberlos confundido. :( –

0

No hay una forma real de hacerlo. Haría la relación floja, consulta para los objetos padres. Después de las protecciones, no inicialice la lista diferida y ejecute otra consulta basada en la primera consulta, que se ejecute en la tabla secundaria. De esta forma, puede limitar el conjunto de resultados en los criterios principales y no en un criterio de unión. O puede ejecutar solo la segunda consulta (solo en la tabla secundaria), con soporte de paginación.

2

El problema real es la propia colección. Debería no modelar su dominio comercial de esta manera. Esta solución (de colecciones anotadas con @OneToMany) solo es viable para colecciones pequeñas (docenas de objetos) y no para grandes (miles de objetos) lo cual puede ser el caso con comentarios. Realmente tienes que tener cuidado con ellos, ya que pueden crecer rápidamente fuera de control. Los estoy usando en este momento solo para modelar la colección de Role asociada con un Account, porque sé que ninguna cuenta tendrá más de 9 funciones en mi dominio y porque los roles en los que se encuentra una cuenta son muy importantes para trabajar con la cuenta Para todas las demás relaciones m-to, estoy usando simples consultas antiguas.

En lugar de añadir una colección de comentarios a su objeto, agregue una referencia al objeto en Comment y explícitamente obtener los comentarios que desee mediante una consulta.

definir una consulta con nombre en Comment para obtener los comentarios para un determinado objeto (vamos a usar Article):

@Entity 
@NamedQueries(value={ 
    @NamedQuery(name=Comment.FOR_ARTICLE, query= 
     "SELECT c FROM Comment c WHERE c.article = :article" 
    ) 
}) 
public class Comment { 
    // ... 
    @ManyToOne 
    @JoinColumn(name = "articleId") 
    private Article article; 
} 

Entonces, el uso que da nombre a la consulta i.c.w. Query.setMaxResults y Query.setFirstResult para controlar de forma explícita el número de resultados a obtener y permitir la paginación, etc:

@PersistenceContext 
EntityManager em; 

Article theArticle = ...; 

Query query = em.createNamedQuery(Comment.FOR_ARTICLE, Comment.class); 
query.setParameter("article", theArticle); 
query.setFirstResult(0); 
query.setMaxResults(10); 
List<Comment> comments = (List<Comment>) query.getResultList(); 

hacer la paginación, simplemente setFirstResult para el primer resultado corresponde con la página que desea mostrar. P.EJ. para mostrar los resultados 20 .. 29, llamaría al setFirstResult(20).

Cuestiones relacionadas