首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

EJB 3 開發指南(13):Servlet 中使用應用程式管理的 EntityManager

     編輯:Java 相關知識

前文介紹的容器管理 EntityManager(Container-Managed, CMT)由 EJB 容器負責生命週期,僅適用於 Session Bean 等受管元件。若在 Servlet、JSF Managed Bean 或獨立 Java SE 環境中需直接操作 JPA,必須改用應用程式管理 EntityManager(Application-Managed, AMT)。本文詳解配置差異與程式碼實作。

核心差異對照

特性容器管理應用程式管理
建立方式@PersistenceContext 注入EntityManagerFactory.createEntityManager()
交易類型JTA (Java EE 容器交易)RESOURCE_LOCAL (本地交易)
關閉責任容器自動管理開發者手動 em.close()、emf.close()
適用場景EJB、CDI Bean、JSF Managed BeanServlet、Filter、獨立應用、測試程式

一、修改 persistence.xml:切換至 RESOURCE_LOCAL

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://java.sun.com/xml/ns/persistence"
             xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://java.sun.com/xml/ns/persistence
                                 https://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
             version="1.0">
  <persistence-unit name="myentity" transaction-type="RESOURCE_LOCAL">
    <non-jta-data-source>java:/MyPIM</non-jta-data-source>
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="none" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
      <property name="hibernate.format_sql" value="true" />
      <property name="hibernate.show_sql" value="true" />
    </properties>
  </persistence-unit>
</persistence>

兩處關鍵修改

  1. transaction-type="RESOURCE_LOCAL":聲明使用本地交易,而非 JTA
  2. <non-jta-data-source>:替換原 <jta-data-source>,資料源名稱不變

提示:若同專案仍需容器管理 EM,可在同檔案新增另一個 <persistence-unit> 並指定不同 name。

二、Servlet 程式碼實作

public class MyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 1. 建立 EntityManagerFactory(昂貴操作,實際專案應做成單例或注入)
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("myentity");

        // 2. 建立 EntityManager
        EntityManager em = emf.createEntityManager();

        try {
            // 3. 業務操作:查詢 ID=1 的 DateBean
            DateBean db = em.find(DateBean.class, 1);
            response.getWriter().println(db.getMyDate());
        } finally {
            // 4. 必須關閉 EM 與 EMF 釋放資源
            em.close();
            emf.close();
        }
    }
}

三、交易控制補充

AMT 模式下需手動管理交易:

EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
    tx.begin();
    // persist / merge / remove 操作
    tx.commit();
} catch (Exception e) {
    if (tx.isActive()) tx.rollback();
    throw e;
} finally {
    em.close();
}

四、效能與最佳實踐

  • EntityManagerFactory 是執行緒安全且重量級:應用程式啟動時建立單例,關閉時釋放,切勿每請求建立。
  • EntityManager 非執行緒安全:每請求/每交易建立一個,用完即關閉。
  • ServletContextListener 初始化 EMF:
@WebListener
public class EMFListener implements ServletContextListener {
    private static EntityManagerFactory emf;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        emf = Persistence.createEntityManagerFactory("myentity");
        sce.getServletContext().setAttribute("emf", emf);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        if (emf != null && emf.isOpen()) emf.close();
    }

    public static EntityManagerFactory getEMF() { return emf; }
}

Servlet 中取得:EntityManager em = EMFListener.getEMF().createEntityManager();

總結

掌握 AMT 模式,讓 JPA 能脫離 EJB 容器在更廣泛的 Java 環境中運作。記住三原則:EMF 單例、EM 請求級、交易手動控制、資源必釋放。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved