@OneToMany mapping list size limit

巧了我就是萌 提交于 2019-11-30 01:37:27

问题


Is there any way to limit the list's size of the @OneToMany relationship in JPA? Here's my code sample:

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

I'm using EclipseLink 2.3 JPA implementation. Thanks in advance.


回答1:


Part of the Bean Validation Specification (JSR-303) is the @Size(min=, max=) annotation:

Supported types are String, Collection, Map and arrays. Check if the annotated element size is between min and max (inclusive).

You could validate the collection.

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



回答2:


The real problem is the collection itself. You should not model your business domain this way. This solution (of collections annotated with @OneToMany) is only viable for small collections (dozens of objects) and not for large ones (thousands of objects) which may very well be the case with comments. You really have to watch out with them as they can quickly grow out of control. I am using them at the moment only to model the collection of Roles associated with an Account, because I know that no account will ever have more than 9 roles in my domain and because the roles an account is in is so very vital to working with the account. For all other m-to-n relations I am using plain old queries.

Instead of adding a collection of comments to your object, add a reference to the object on Comment and explicitly get the comments you want using a query.

Define a named query on Comment to get the comments for a certain object (let's use 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;
}

Then, use that named query i.c.w. Query.setMaxResults and Query.setFirstResult to explicitly control how many results to get and allow for paging 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();

To do paging, just setFirstResult to the first result corresponding with the page you want to display. E.G. to show results 20 .. 29, you would call setFirstResult(20).




回答3:


You cannot do this in JPA and it doesn't make sense because mappings are designed to reflect the reality of how many objects are in the relationship.

Are you doing this because of performance? If so what you can do is to use a Lazy fetch style and use the Batchsize annotation to specific how many you want to fetch once:

*correction: @Batchsize is a Hibernate feature

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

Then in your code, simply only iterate/loop to where you want in this mapped collection.

Either way, from my experience "hacking" mappings to do what Criterias/Querys are designed for is not a fruitful endeavor, when you need more control or performance-tuning than the @OneToMany explicitly provides, the best way might be to just make a query.




回答4:


No real ortodox way of doing this. I would make the relation lazy, query for the parent objects. After wards do not initialize the lazy list, and run another query based on the first query, that runs on the child table. This way you can limit the result set on the main criteria and not on a join criteria. Or you can run only the second query (only on the child table), with pagination support.



来源:https://stackoverflow.com/questions/7894931/onetomany-mapping-list-size-limit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!