Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I do paging with @OneToMany collections

Suppose I have a Post entity and a Comment entity and a one to many relationship:

@Entity class Post {
    ...
    @OneToMany
    List<Comment> comments;
    ...
}

How can I achieve paging like this:

Post post = //Find the post.
return post.getComments().fetch(100, 10); // Find the 11th page (page size 10);

Is it possible to emulate dynamic paging with @OneToMany collections on top of JPA, or do we have to rewrite the association mechanism of JPA totally ? (e.g. create a PersistentList collection type that could manage the paging, sorting and searching).

P.S.: I recently found the Play! framework uses a very interesting lib on top of JPA: Siena. Siena is very easy to use, and is a good abstraction on top of JPA/Hibernate. But I can't find how to do paging with its associations.

Update:

Play framework has a query syntax similar to Django:

Post.findAll().from(100).fetch(10);  // paging

where

Post.findAll() 

will return a JPAQuery object, a customized query type in Play.

But with associated collections, e.g.:

Post.comments

will just return a List, which doesn't support paging or other queries.

I was wondering how to extend it, so that

Post.comments

will also return a JPAQuery object or similar, then you can query on the "query" collection:

Post.comments.from(100).fetch(10);

or insert a new Comment without actually fetching any of the comments:

Post.comments.add(new Comment(...));

On my first thought, we could create a subclass of List, then the Post class would become:

@Entity class Post {
    ...
    @OneToMany
    QueryList<Comment> comments;
    ...
}

and QueryList will have fetch(), from() methods that indirect to JPAQuery's.

But I don't know whether Hibernate/JPA will recognize this, or interfere with it.

like image 675
Visus Zhao Avatar asked Oct 19 '10 16:10

Visus Zhao


People also ask

How do I map OneToMany?

Create an entity class Student. java under com. javatpoint. mapping package that contains student id (s_id), student name (s_name) with @OneToMany annotation that contains Library class object of List type.

How does pagination work in hibernate?

Pagination is a simple but important feature to limit the size of your result set to a number of records that can get efficiently processed by your application and the user. You can configure it with JPA and Hibernate by calling the setFirstResult and setMaxResults on the Query or TypedQuery interface.

What is the difference between mappedBy and @JoinColumn?

The @JoinColumn annotation helps us specify the column we'll use for joining an entity association or element collection. On the other hand, the mappedBy attribute is used to define the referencing side (non-owning side) of the relationship.

How do you implement a one to many relationship in Java?

You can ensure that there are no duplicates by using a Set implementation like HashSet instead of using other data-structure. And instead of adding Job to a customer, create an final inner class in Job class that has private constructor. That ensure that the wrapper inner class can only be created by a job object.


2 Answers

Is it possible to emulate dynamic paging with @OneToMany collections on top of JPA (...)

Not supported. The standard approach would be to use a JPQL query to retrieve the comments for a given post and and to use Query#setFirstResult(int) and Query#setMaxResults(int).

On my first thought, we could create a subclass of List, (...). But I don't know whether Hibernate/JPA will recognize this, or interfere with it.

It obviously won't without an heavy patch to drastically change the default behavior.

like image 114
Pascal Thivent Avatar answered Sep 28 '22 08:09

Pascal Thivent


I think the "right" way might be more like:

@Entity
class Post {
    ...

    public GenericModel.JPAQuery getComments() {
        return Comment.find("post_id = ?", post_id);
    }
}

and then use one of the fetch methods in JPAQuery:

// fetch first page of results, 25 results per page
post.getComments().fetch(1,25);
like image 30
Brad Mace Avatar answered Sep 28 '22 08:09

Brad Mace