Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

jpacontainer-hibernate.asciidoc 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. ---
  2. title: Using JPAContainer with Hibernate
  3. order: 9
  4. layout: page
  5. ---
  6. [[jpacontainer.hibernate]]
  7. = Using JPAContainer with Hibernate
  8. Hibernate needs special handling in some cases.
  9. [[jpacontainer.hibernate.lazyloading]]
  10. == Lazy loading
  11. In order for lazy loading to work automatically, an entity must be attached to
  12. an entity manager. Unfortunately, Hibernate can not keep entity managers for
  13. long without problems. To work around the problem, you need to use a special
  14. lazy loading delegate for Hibernate.
  15. JPAContainer entity providers handle lazy loading in delegates defined by the
  16. [interfacename]#LazyLoadingDelegate# interface. The default implementation for
  17. Hibernate is defined in [classname]#HibernateLazyLoadingDelegate#. You can
  18. instantiate one and use it in an entity provider with
  19. [methodname]#setLazyLoadingDelegate()#.
  20. The default implementation works so that whenever a lazy property is accessed
  21. through the Vaadin Property interface, the value is retrieved with a separate
  22. (JPA Criteria API) query using the currently active entity manager. The value is
  23. then manually attached to the entity instance, which is detached from the entity
  24. manager. If this default implementation is not good enough, you may need to make
  25. your own implementation.
  26. ifdef::web[]
  27. [[jpacontainer.hibernate.em-per-request]]
  28. == The EntityManager-Per-Request pattern
  29. One issue with Hibernate is that it is designed for short-lived sessions, but
  30. the lifetime of an entity manager is normally roughly that of a user session.
  31. The problem is that if an error occurs in a session or an entity manager, the
  32. manager becomes unuseable. This causes big problems with long-lived sessions
  33. that would work fine with EclipseLink.
  34. The recommended solution is to use the __EntityManager-per-Request__ pattern. It
  35. is highly recommended always when using Hibernate.
  36. An entity manager can only be open during the request-response cycle of the
  37. Vaadin servlet, so that one is created at the beginning of the request and
  38. closed at the end.
  39. [[jpacontainer.hibernate.em-per-request.provider]]
  40. === Storing an Entity Manager
  41. You first need to implement an [interfacename]#EntityManagerProvider# that
  42. returns a stored [interfacename]#EntityManager# with
  43. [methodname]#getEntityManager()#. The entity manager must be stored in a
  44. [classname]#ThreadLocal# variable.
  45. ----
  46. public class LazyHibernateEntityManagerProvider
  47. implements EntityManagerProvider {
  48. private static ThreadLocal<EntityManager>
  49. entityManagerThreadLocal =
  50. new ThreadLocal<EntityManager>();
  51. @Override
  52. public EntityManager getEntityManager() {
  53. return entityManagerThreadLocal.get();
  54. }
  55. public static void setCurrentEntityManager(
  56. EntityManager em) {
  57. entityManagerThreadLocal.set(em);
  58. }
  59. }
  60. ----
  61. You need to create and store the per-request instance at the beginning of each
  62. request with [methodname]#setCurrentEntityManager()# and clear it at the end by
  63. setting it as [literal]#++null++#.
  64. [[jpacontainer.hibernate.em-per-request.provider]]
  65. === Creating Entity Managers in a Servlet Filter
  66. You can create the entity managers for each request either by extending
  67. [classname]#VaadinServlet# and overriding the [methodname]#service()# method or
  68. by implementing a servlet filter. In the following, we describe how to implement
  69. a servlet filter to do the task, but overriding the servlet could be even
  70. easier.
  71. ----
  72. public class LazyHibernateServletFilter
  73. implements Filter {
  74. private EntityManagerFactory entityManagerFactory;
  75. @Override
  76. public void init(FilterConfig filterConfig)
  77. throws ServletException {
  78. entityManagerFactory = Persistence
  79. .createEntityManagerFactory("lazyhibernate");
  80. }
  81. @Override
  82. public void doFilter(ServletRequest servletRequest,
  83. ServletResponse servletResponse,
  84. FilterChain filterChain)
  85. throws IOException, ServletException {
  86. try {
  87. // Create and set the entity manager
  88. LazyHibernateEntityManagerProvider
  89. .setCurrentEntityManager(
  90. entityManagerFactory
  91. .createEntityManager());
  92. // Handle the request
  93. filterChain.doFilter(servletRequest,
  94. servletResponse);
  95. } finally {
  96. // Reset the entity manager
  97. LazyHibernateEntityManagerProvider
  98. .setCurrentEntityManager(null);
  99. }
  100. }
  101. @Override
  102. public void destroy() {
  103. entityManagerFactory = null;
  104. }
  105. }
  106. ----
  107. You need to define the servlet filter in the [filename]#web.xml# deployment
  108. descriptor as follows:
  109. [subs="normal"]
  110. ----
  111. &lt;filter&gt;
  112. &lt;filter-name&gt;**LazyHibernateServletFilter**&lt;/filter-name&gt;
  113. &lt;filter-class&gt;**com.example.LazyHibernateServletFilter**&lt;/filter-class&gt;
  114. &lt;/filter&gt;
  115. &lt;filter-mapping&gt;
  116. &lt;filter-name&gt;**LazyHibernateServletFilter**&lt;/filter-name&gt;
  117. &lt;url-pattern&gt;**/++*++**&lt;/url-pattern&gt;
  118. &lt;/filter-mapping&gt;
  119. ----
  120. The [literal]#++url-pattern++# must match the pattern for your Vaadin servlet.
  121. endif::web[]
  122. [[jpacontainer.hibernate.joins]]
  123. == Joins in Hibernate vs EclipseLink
  124. EclipseLink supports implicit joins, while Hibernate requires explicit joins. In
  125. SQL terms, an explicit join is a " [literal]#++FROM a INNER JOIN b ON a.bid =
  126. b.id++#" expression, while an implicit join is done in a WHERE clause, such as:
  127. " [literal]#++FROM a,b WHERE a.bid = b.id++#".
  128. In a JPAContainer filter with EclipseLink, an implicit join would have form:
  129. ----
  130. new Equal("skills.skill", s)
  131. ----
  132. In Hibernate you would need to use [classname]#JoinFilter# for the explicit
  133. join:
  134. ----
  135. new JoinFilter("skills", new Equal("skill", s))
  136. ----