|
The pattern
So now that we know how to configure lazy loading and how it works, how can we use it properly?
Step 1 would be to examine all your associations and see which should be lazily loaded and which should be eagerly loaded. As a rule of thumb I start out leaving all *-to-one associations eager (the default). They usually don't add up to a large number of queries anyway and if they do, I can change them. Then I examine all *-to-many associations. If any of them are to entities that are always accessed and therefore always loaded, I configure them to be loaded eagerly. And sometimes I use the Hibernate specific @CollectionOfElements annotation to map such "value type" entities.
Step 2 is the most important. To prevent any LazyInitializationExceptions or NullPointerExceptions you need to make sure that all access to your domain objects occurs within one transaction. When domain objects are accessed after a transaction has finished, the persistence context can no longer be accessed to load the lazy objects, and that causes these problems. There are two ways to solve this:
1. The most pure way is to place a Service Facade (or Remote Facade if you will) in front of your services and only communicate with clients of your service facade through Transfer Objects (a.k.a. Data Transfer Objects a.k.a. DTO's). The facade's responsibility is to copy all appropriate values from your domain objects to the data transfer objects, including making deep copies of references and collections. The transaction scope of your application should include the service facade for this pattern to work, i.e. set your facade to be @Transactional or give it a proper @TransactionAttribute.
2. If you are writing a Model 2 web application with an MVC framework, a widely used alternative is to use the open EntityManager in view pattern. In Spring you can configure a Servlet filter or a Web MVC interceptor that will open the entity manager when a request comes in and will keep it open until the request has been handled. The means the same transaction is active in your controller and in your view (JSP or otherwise). While purists may argue that this makes your presentation layer depends on your domain objects, it is a compelling approach for simple web applications.
Step 3 is to enable SQL logging of your JPA provider and exercise some of the use cases of your applications. It is enlightening to see what queries are performed when entities are accessed. The SQL log can also provide you with input for performance optimizations so you can revisit the decisions you made in step 1 and tune your database. In the end lazy loading is all about performance, so don't forget this step!
I hope this blog has given you some insight into how lazy loading works and how you can use it in your application. In the next blog I will delve deeper into the topic of the DTO and Service Facade patterns. But before I leave you I would like to thank everybody that came to my J-Spring 2009 talk on this subject. I had a lot of fun! It really seems a lot of people are wondering how to effectively use JPA because I got a lot of questions. Unfortunately the questions made me run out of time. Next time I will pay more attention to the girl with the time card. And bring my own water. ;-) Thanks again for being there!
P.S. Does anybody know what happened to hibernate.org? For more than a week the site has been showing a message saying they are down for maintenance. |
|