views:

76

answers:

1

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.

+2  A: 

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.

Pascal Thivent
Thanks a lot :)
Visus Zhao
BTW. I found that Hibernate will "intercept" the @OneToMany Collection, and indirect it into a query. So is it possible to "plugin" Hibernate system with a customized collection type (e.g. @OneToMany LazyQueryList, which has a fetch(start, offset) method), that Hibernate will recognize?
Visus Zhao
@Visus It should be possible to **patch** Hibernate, which is very different from a plugin mechanism, and this won't be a trivial patch. Good luck if you decide to go this direction.
Pascal Thivent
Thanks for the clarification. I'm new with hibernate, and a heavy patch is definitely beyond my ability. But I'm still stuck with how to use associations effectively. I saw you talk about projects using hibernate in a bad way - 'not using associations because they were scared to "fetch the whole database"', in a reply to another question. I'd really like to know how NOT to retrieve a whole collection. Or, in the case of manually creating JPQL queries for the collection, does that mean we use the association collection only for the mapping? How can we set them back to Post.comments?
Visus Zhao
`I'd really like to know how NOT to retrieve a whole collection` Make it LAZY, or maybe even [EXTRA](http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-singleassoc-fetching) lazy. `Or, in the case of manually creating JPQL queries for the collection, does that mean we use the association collection only for the mapping?` For querying also.
Pascal Thivent
So I guess when the collection is small, just use something like Post.getComments(); and when it is potentially large, avoid the Post.getComments() and make another query (paged if needed), and use the result list independently. Is that the right practice?
Visus Zhao
@Visus That's at least what I consider as the right practice.
Pascal Thivent
Thanks! I'll try to follow this practice.
Visus Zhao