Hibernate needs special handling in some cases.
In order for lazy loading to work automatically, an entity must be attached to an entity manager. Unfortunately, Hibernate can not keep entity managers for long without problems. To work around the problem, you need to use a special lazy loading delegate for Hibernate.
JPAContainer entity providers handle lazy loading in delegates defined by
the LazyLoadingDelegate
interface. The
default implementation for Hibernate is defined in
HibernateLazyLoadingDelegate
. You can instantiate
one and use it in an entity provider with
setLazyLoadingDelegate()
.
The default implementation works so that whenever a lazy property is accessed through the Vaadin Property interface, the value is retrieved with a separate (JPA Criteria API) query using the currently active entity manager. The value is then manually attached to the entity instance, which is detached from the entity manager. If this default implementation is not good enough, you may need to make your own implementation.
One issue with Hibernate is that it is designed for short-lived sessions. The lifetime of an entity manager is roughly that of a session. However, if an error occurs in a session or entity manager, the manager becomes unuseable. This causes big problems with long-lived sessions that would work fine with EclipseLink.
The recommended solution is to the EntityManager-per-Request pattern. It is highly recommended always when using Hibernate.
An entity manager can only be open during the request-response cycle of the Vaadin application servlet, so that one is created at the beginning of the request and closed at the end.
You can use the EntityManagerPerRequestHelper
as
follows:
Create a new instance in the constructor or
init()
method of your Vaadin application
class.
Override onRequestStart()
in the
application class and call requestStart()
in the helper instance.
Override onRequestEnd()
in the
application class and call requestEnd()
in the helper.
Whenever a new JPAContainer
instance is
created in the application, register it in the helper by calling
addContainer()
with the container.
If you use the JPAContainer FieldFactory
,
as described in Section 18.8, “Automatic Form Generation”, you
need to set the helper for the factory either by passing it in the
constructor (new FieldFactory(myEMPRH)
) or with
setEntityManagerPerRequestHelper()
. The
FieldFactory
creates
JPAContainer
s internally and these
instances need to be updated with the entity manager instances
when they change between requests.
EclipseLink supports implicit joins, while Hibernate requires explicit
joins. In SQL terms, an explicit join is a "FROM a INNER JOIN b
ON a.bid = b.id
" expression, while an implicit join is done in a
WHERE clause, such as: "FROM a,b WHERE a.bid = b.id
".
In a JPAContainer filter with EclipseLink, an implicit join would have form:
new Equal("skills.skill", s)
In Hibernate you would need to use JoinFilter
for
the explicit join:
new JoinFilter("skills", new Equal("skill", s))