The standard fetch strategy for collections in hibernate is lazy select fetching (hibernate performance). So if you retrieve some entities (for example via a query or a collection association) with a lazy collection association, subsequent calls to this lazy association will be retrieved one by one in further requests, for example. This is called the N+1
-query problem, since there is one query for retrieving the entities itself and N
additional queries for the lazy association. You can reduce the overhead by setting the hibernate.default_batch_fetch_size
for your persistence unit in the persistence.xml
. This reduces the problem to an N/batch_size +1
-query problem. You can tell hibernate to use only 1+1
-queries, if you set the fetch strategy to subselect fetching. This way, all entities in the association collections of the entities are retrieved in one query as soon as one of the associations is accessed. This will be helpfull only, if you do not pick one of the objects and retrieve the association, but iterate through your results and access the association of each of them. It is even contra productive otherwise. If you like to use annotations for configuration of your entities, you need the hibernate-annotations. If you are using JPA this will add hibernate specific code to your application. But if you flip between your persistence provider the other one will hopefully ignore the hibernate annotations. So this is the code:
import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; // ... @Entity @Table public class MyEntity { private Collection<OtherEntity> otherEntities; //... @OneToMany @Fetch(FetchMode.SUBSELECT) public Collection<OtherEntity> getOtherEntities() { return this.otherEntities; } }
This fancy fetch strategy does a pretty good job, especially when your associations tend to get big.
Hi, it is not exactly the same configuration, but it seems that hibernate ignores my annotation @Fetch. I use jpa 2 with hibernate 4.0.1.
In my example i have a @ManyToOne asociation with @Fetch(FetchMode.JOIN) and it does n + 1 query. Search in the web and forums many people says that it is a bug that never was resolved, how it works for you? Any idea?
Thanks