JPAContainer lazy nested property issue

Is it possible to add a nested property to a JPAContainer, if the property is lazy loaded ?

The behaviour I’m seeing suggests not.

E.g.

saleContractJPAContainer.addNestedContainerProperty(“salesExecutive.*”);

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "SALES_EXEC_ID")    
public SalesExecutive getSalesExecutive() {
    return salesExecutive;
}

This fails with a lazy load exception.

I’m pretty sure this worked in 6.5.?

Thanks
Phil

This has always been problematic with Hibernate - and not only with Vaadin. Hibernate is designed for inexpensive short sessions and (by design) does not support lazy loading when accessing an entity in a later session (request). For other reasons (how Hibernate reacts to errors), using JPA sessions that span requests is also problematic. If the access to the lazy field is explicit in your code, you could try to first force re-attaching the main entity to the session - but then you might run into the problem that JPA does not really provide an API for that apart from merge(), which might also save some changes.

With EclipseLink, lazy loading works somewhat better - although you should realize the lazy field might then be loaded in a different DB transaction than the main entity. Usually this is not a problem, e.g. optimistic locking is sufficient to handle such situations in many simple applications.

The latest versions of JPAContainer have some workarounds to JPA issues related to lazy fields but primarily concerning saving changes. More significantly, they have been updated to use the Vaadin 6.6 filtering system, so I believe you are already using a relatively recent version.

As for changes between 6.5 and 6.6, I don’t see how container related changes would have affected this, but in some cases changes to some component displaying the data (ComboBox/… or Table) might be related. To what UI components is your container linked and does the UI component directly display the lazy field value?

Thanks, I appreciate the response.

The component I’m populating is a table.

My assumption was that by using
addNestedContainerProperty
the JPAContainer would eagerly fetch the property.
I.e. apply a join.

I think I’m having a similar problem and I don’t know how to go about solving it. I’m loading a ‘User’ object from my database and the user has Roles associated with it. My JPAContainer loads the user(s) properly, but later in my code I want to iterate through the roles, and it throws a LazyInitializationException. So what workarounds are there in the JPAContainer? My class code looks something like this:

class User{
String name;

//bi-directional many-to-many association to UserRole
@ManyToMany(mappedBy=“users”)
private List userRoles;


public List getUserRoles() {
return this.userRoles;
}

Calling getUserRoles() works, but trying to access the list of roles fails - I’m loading the JPAContainer with all my users, and then later picking out an individual user object from that list to work with… I don’t want to load all the roles of all the users if I don’t have to - so I need a way to force loading of the roles for a single user. I am using Hibernate for this.

Thanks,

nbc

Hi,

Maybe “open session in view pattern” is what you are looking for?

Cheers,
Roland

“My assumption was that by using addNestedContainerProperty the JPAContainer would eagerly fetch the property.
I.e. apply a join.”

I was very surprised it didn’t myself. Even if lazy loading via a delegate or EclipseLink’s built-in background loading is possible, it’s not ideal. Lazy loading can be slow, can’t be batched properly and often occurs in a separate transaction so the results can be inconsistent; the entity you’re fetching might’ve even vanished in some operation between the initial fetch and the lazy load.

Time permitting I’ll have to go diving in the JPAContainer sources to see how it builds its queries and whether it can be convinced to eagerly fetch nested properties using ‘fetch join’, EclipseLink query hints, or Criteria Root.fetch(…) . Hopefully EclipseLink hints can be used to get efficient batch fetches when EclipseLink is in use, and otherwise a fallback to fetch joins would be needed.

It’s a real pity JPA doesn’t allow you to specify a fetch stragegy the way Hibernate does natively; it’s often much faster to fetch an entity set then fetch dependent entities in batches via SELECT … WHERE key IN (…) than it is to join, retrieve tons of duplicate data, and de-duplicate. That’s the only option JPA offers on a query-by-query basis, though.

This is an issue that I wrestled with in several projects. I believe the best approach is to include fetch joins in your query and not allow JPA to lazily fetch any related entities, except read-only reference entities that are cached.

The caveat is that once you use fetch joins in your query, then Hibernate reads ALL results into memory and pages in memory, which is a no-go for paging through large result sets. This is widely discussed limitation of Hibernate.

So, I implemented a three-stage query solution in
ExpressUI
, which you can read about in the Query Beans section of my tutorial:
http://www.expressui.com/tutorial/

Related Javadoc:
http://www.expressui.com/wp-content/uploads/api/1.0.x/com/expressui/core/dao/query/StructuredEntityQuery.html

My approach allows you to modularize your query and handle variable search criteria, paging, sorting and avoid the N+1 select performance problem, which can occur if you rely on lazy fetching. If you want to dig into the technical details, my framework code in available on
GitHub
. See implementation of GenericDao.StructuredQueryExecutor.

Juan

Thanks for the pointer to ExpressUI. I’m glad I’m not the only one having issues. I’ll have to give ExpressUI a go, but I suspect my data model will prove a bit tricky for it and I’m not sure I can change the possible problem areas without creating worse ones elsewhere. Still, very interesting and well worth a go.

Weird how JPA and fetch issues seems to crop up everywhere, isn’t it? The JPA 2.1 expert group has fetch control on its agenda, though. Please help me push the issue with the EG! See
this
post, and PLEASE join
http://java.net/projects/jpa-spec
to make your experiences and concerns known on the jpa-spec users mailing list. Without real world in-the-trenches feedback, JPA 2.1 won’t fix the issues with JPA 2.0.

Please get involved!

JPAContainer’s ID-based design makes it a lot worse as it doesn’t ask for ranges of objects when it loads them. The poor database is doing endless sort-offset-limit queries, possibly with joins for eager properties. It needs a re-design to allow the persistence provider to fetch more intelligently; right now the provider doesn’t get enough information to group and batch work effectively.

Looking at my DB logs, it seems to be even worse than I’d feared at the moment. With EclipseLink I’m seeing one query per entity per property. Seven queries per entity, each just a re-fetch of the entity all over again:

LOG: execute : SELECT id, … property list … FROM entity WHERE (id = $1)
DETAIL: parameters: $1 = ‘108793’
LOG: execute : SELECT id, … property list … FROM entity WHERE (id = $1)
DETAIL: parameters: $1 = ‘108793’
LOG: execute : SELECT id, … property list … FROM entity WHERE (id = $1)
DETAIL: parameters: $1 = ‘108793’
LOG: execute : SELECT id, … property list … FROM entity WHERE (id = $1)
DETAIL: parameters: $1 = ‘108793’

It’s also re-executing the filter query very frequently. I see literally thousands of queries when I scroll one page down in a table. Is this expected? It’s pretty much pessimal for JPA2, the worst behaviour you can get. setEntitiesDetached(false) doesn’t help.

I’m using the LocalEntityProvider so of course I’ll try the CachingLocalEntityProvider, but if the API is producing this kind of query pattern than I suspect CachingLocalEntityProvider will be gilding a toad. It shouldn’t be necessary to cache with such simple cases unless the API is a poor fit for the task.