Question

I am currently working on a distributed application using the following components:

1.tier: Database-Server -> MySQL 5.5

2.tier: Application-Server -> Glassfish 3.1.2.2

3.tier: Stand-alone Fat-Client -> Java-SE (JRE 6)

I use JPA 2.0 (eclipse-link) as persistence provider and currently passing the @Entity beans between the 2nd and 3rd tier using serialization. I use static weaving in order to benefit from lazy fetching supported by JPA.

My problem is, that because of serialization between 2nd/3rd tier lazy fetching won't work! That results in heavy network traffic, since every serialization of one of my entity beans requires that all relationships to other entities/tables are fetched before sent over the network.

How can I benefit from JPA lazy fetching in such a setup? Is there a work-around without the need to introduce leightweight DTO/DAO (this would add huge complexity to my project) ?

Many thanks for your help in advance!

Was it helpful?

Solution 2

We solved this issue by using load groups and query hints in order to define the depth of the relations that should be fetched in a particular query. This requires lazy fetching and therefore weaving when using eclipse-link as JPA provider.

Here's a short example:

Server side query on a particular facade:

@Override
public List<Contact> query(LoadGroup group) {
    TypedQuery<Contact> query = em.createQuery("SELECT c FROM Contact c", Contact.class);
    if(group!=null) { query.setHint(QueryHints.LOAD_GROUP, group); }
    return query.getResultList();
}

Client side query on that particular facade:

LoadGroup group = new LoadGroup();
group.addAttribute("telephone");
group.addAttribute("address.street");
List<Contact> contacts = remoteContactFacade.query(group);

In this example the Contact table has further many-to-one relations to the Address and Telephone tables. By using the dot notation you can define the depth of what should be fetched.

Hope this helps.

OTHER TIPS

In my experience on a similar architecture, for a quite big project, DTOs are unavoidable and should be used when necessary.

Working with detached entities, especially when they have multiple associations with other entities, not only causes performance problems due to the database loading and serialization, but also a huge complexity. Indeed, unless the code is extremely well documented, it's hard to know in the presentation layer whether a given association is loaded or not, which causes a whole lot of lazy initialization exceptions.

It's even worse if you send back serialized detached entities from the presentation layer to the service layer, because then you end up with code using a mix of detached and attached entities, which makes things even more complex.

My advices would thus be:

  • transfer entities from the service layer to the UI layer if the entity is simple and the UI layer doesn't need too many loaded associations. Always document which of the associations are initialized, and which are not. If too many associations, use DTOs, and ad hoc queries to load the necessary data from the database.
  • transfer DTOs from the service layer to the UI layer when a big number of entities are needed (for example, the result of a search form returning O(100) results or more). Use an ad hoc query to load the requested data.
  • avoid transferring entities from the presentation layer to the service layer. If you do, make sure that the first thing you do in the service layer is reloading an attached version of the entity from the database, or merging the received entity, in order to always work with attached entities. Debugging a lazy initialization exception thrown in the service layer and cause by the use of a detached entity that has been loaded several minutes ago by a previous screen is not a piece of pleasure.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top