summaryrefslogtreecommitdiffstats
path: root/documentation/jpacontainer/jpacontainer-hibernate.asciidoc
diff options
context:
space:
mode:
authorelmot <elmot@vaadin.com>2015-09-25 16:40:44 +0300
committerelmot <elmot@vaadin.com>2015-09-25 16:40:44 +0300
commita1b265c318dbda4a213cec930785b81e4c0f7d2b (patch)
treeb149daf5a4f50b4f6446c906047cf86495fe0433 /documentation/jpacontainer/jpacontainer-hibernate.asciidoc
parentb9743a48a1bd0394f19c54ee938c6395a80f3cd8 (diff)
downloadvaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.tar.gz
vaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.zip
Framework documentation IN
Change-Id: I767477c1fc3745f9e1f58075fe30c9ac8da63581
Diffstat (limited to 'documentation/jpacontainer/jpacontainer-hibernate.asciidoc')
-rw-r--r--documentation/jpacontainer/jpacontainer-hibernate.asciidoc180
1 files changed, 180 insertions, 0 deletions
diff --git a/documentation/jpacontainer/jpacontainer-hibernate.asciidoc b/documentation/jpacontainer/jpacontainer-hibernate.asciidoc
new file mode 100644
index 0000000000..de7f26d9a0
--- /dev/null
+++ b/documentation/jpacontainer/jpacontainer-hibernate.asciidoc
@@ -0,0 +1,180 @@
+---
+title: Using JPAContainer with Hibernate
+order: 9
+layout: page
+---
+
+[[jpacontainer.hibernate]]
+= Using JPAContainer with Hibernate
+
+Hibernate needs special handling in some cases.
+
+[[jpacontainer.hibernate.lazyloading]]
+== Lazy loading
+
+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
+[interfacename]#LazyLoadingDelegate# interface. The default implementation for
+Hibernate is defined in [classname]#HibernateLazyLoadingDelegate#. You can
+instantiate one and use it in an entity provider with
+[methodname]#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.
+
+
+ifdef::web[]
+[[jpacontainer.hibernate.em-per-request]]
+== The EntityManager-Per-Request pattern
+
+One issue with Hibernate is that it is designed for short-lived sessions, but
+the lifetime of an entity manager is normally roughly that of a user session.
+The problem is that if an error occurs in a session or an 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 use 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 servlet, so that one is created at the beginning of the request and
+closed at the end.
+
+[[jpacontainer.hibernate.em-per-request.provider]]
+=== Storing an Entity Manager
+
+You first need to implement an [interfacename]#EntityManagerProvider# that
+returns a stored [interfacename]#EntityManager# with
+[methodname]#getEntityManager()#. The entity manager must be stored in a
+[classname]#ThreadLocal# variable.
+
+
+----
+public class LazyHibernateEntityManagerProvider
+ implements EntityManagerProvider {
+ private static ThreadLocal<EntityManager>
+ entityManagerThreadLocal =
+ new ThreadLocal<EntityManager>();
+
+ @Override
+ public EntityManager getEntityManager() {
+ return entityManagerThreadLocal.get();
+ }
+
+ public static void setCurrentEntityManager(
+ EntityManager em) {
+ entityManagerThreadLocal.set(em);
+ }
+}
+----
+
+You need to create and store the per-request instance at the beginning of each
+request with [methodname]#setCurrentEntityManager()# and clear it at the end by
+setting it as [literal]#++null++#.
+
+
+[[jpacontainer.hibernate.em-per-request.provider]]
+=== Creating Entity Managers in a Servlet Filter
+
+You can create the entity managers for each request either by extending
+[classname]#VaadinServlet# and overriding the [methodname]#service()# method or
+by implementing a servlet filter. In the following, we describe how to implement
+a servlet filter to do the task, but overriding the servlet could be even
+easier.
+
+
+----
+public class LazyHibernateServletFilter
+ implements Filter {
+
+ private EntityManagerFactory entityManagerFactory;
+
+ @Override
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ entityManagerFactory = Persistence
+ .createEntityManagerFactory("lazyhibernate");
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest,
+ ServletResponse servletResponse,
+ FilterChain filterChain)
+ throws IOException, ServletException {
+ try {
+ // Create and set the entity manager
+ LazyHibernateEntityManagerProvider
+ .setCurrentEntityManager(
+ entityManagerFactory
+ .createEntityManager());
+
+ // Handle the request
+ filterChain.doFilter(servletRequest,
+ servletResponse);
+ } finally {
+ // Reset the entity manager
+ LazyHibernateEntityManagerProvider
+ .setCurrentEntityManager(null);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ entityManagerFactory = null;
+ }
+}
+----
+
+You need to define the servlet filter in the [filename]#web.xml# deployment
+descriptor as follows:
+
+[subs="normal"]
+----
+&lt;filter&gt;
+ &lt;filter-name&gt;**LazyHibernateServletFilter**&lt;/filter-name&gt;
+ &lt;filter-class&gt;**com.example.LazyHibernateServletFilter**&lt;/filter-class&gt;
+&lt;/filter&gt;
+&lt;filter-mapping&gt;
+ &lt;filter-name&gt;**LazyHibernateServletFilter**&lt;/filter-name&gt;
+ &lt;url-pattern&gt;**/++*++**&lt;/url-pattern&gt;
+&lt;/filter-mapping&gt;
+----
+The [literal]#++url-pattern++# must match the pattern for your Vaadin servlet.
+
+
+endif::web[]
+
+[[jpacontainer.hibernate.joins]]
+== Joins in Hibernate vs EclipseLink
+
+EclipseLink supports implicit joins, while Hibernate requires explicit joins. In
+SQL terms, an explicit join is a " [literal]#++FROM a INNER JOIN b ON a.bid =
+b.id++#" expression, while an implicit join is done in a WHERE clause, such as:
+" [literal]#++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 [classname]#JoinFilter# for the explicit
+join:
+
+
+----
+new JoinFilter("skills", new Equal("skill", s))
+----
+
+
+
+