Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>During the last few days I designed a possible solution. What I was trying to construct with the <code>BookUnitSession</code> class was actually the <code>EntityManagerHelper</code> class:</p> <pre><code>public class EntityManagerHelper { private static final EntityManagerFactory emf; private static final ThreadLocal&lt;EntityManager&gt; threadLocal; static { emf = Persistence.createEntityManagerFactory("BookStoreUnit"); threadLocal = new ThreadLocal&lt;EntityManager&gt;(); } public static EntityManager getEntityManager() { EntityManager em = threadLocal.get(); if (em == null) { em = emf.createEntityManager(); threadLocal.set(em); } return em; } public static void closeEntityManager() { EntityManager em = threadLocal.get(); if (em != null) { em.close(); threadLocal.set(null); } } public static void closeEntityManagerFactory() { emf.close(); } public static void beginTransaction() { getEntityManager().getTransaction().begin(); } public static void rollback() { getEntityManager().getTransaction().rollback(); } public static void commit() { getEntityManager().getTransaction().commit(); } } </code></pre> <p>Such a class ensures that each thread (i.e., each request) will get its own <code>EntityManager</code> instance. Consequently, each DAO object can obtain the correct <code>EntityManager</code> instance by calling <code>EntityManagerHelper.getEntityManager()</code></p> <p>According to the session-per-request pattern each request must open and close its own <code>EntityManager</code> instance, which will be in charge of encapsulating the required unit of work within a transaction. This can be done by means of an intercepting filter implemented as a <code>ServletFilter</code>:</p> <pre><code>public class EntityManagerInterceptor implements Filter { @Override public void destroy() {} @Override public void init(FilterConfig fc) throws ServletException {} @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { try { EntityManagerHelper.beginTransaction(); chain.doFilter(req, res); EntityManagerHelper.commit(); } catch (RuntimeException e) { if ( EntityManagerHelper.getEntityManager() != null &amp;&amp; EntityManagerHelper.getEntityManager().isOpen()) EntityManagerHelper.rollback(); throw e; } finally { EntityManagerHelper.closeEntityManager(); } } } </code></pre> <p>This approach also allows the View (e.g., a JSP page) to fetch entity's fields even if they have been lazy initialized (Open Session in View pattern). In a JSE environment the <code>EntityManagerFactory</code> needs to be explicitly closed when the servlet container is shutdown. This can be done by using a <code>ServletContextListener</code> object:</p> <pre><code>public class EntityManagerFactoryListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent e) { EntityManagerHelper.closeEntityManagerFactory(); } @Override public void contextInitialized(ServletContextEvent e) {} } </code></pre> <p>The <code>web.xml</code> deployment descriptor:</p> <pre><code>&lt;listener&gt; &lt;description&gt;EntityManagerFactory Listener&lt;/description&gt; &lt;listener-class&gt;package.EntityManagerFactoryListener&lt;/listener-class&gt; &lt;/listener&gt; &lt;filter&gt; &lt;filter-name&gt;interceptor&lt;/filter-name&gt; &lt;filter-class&gt;package.EntityManagerInterceptor&lt;/filter-class&gt; &lt;/filter&gt; &lt;filter-mapping&gt; &lt;filter-name&gt;interceptor&lt;/filter-name&gt; &lt;url-pattern&gt;*.do&lt;/url-pattern&gt; &lt;/filter-mapping&gt; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload