若您要直接在Servlet中使用JPA,要記得的是,EntityManager不是Thread-safe,所以切記,不可直接將EntityManager注入Servlet中成為物件成員之一,Servlet被共用存取的情況下,會有資料共用存取的問題。
若您要在Servlet中直接使用JPA,有兩種方式可以進行,一是透過在類別上宣告@PersistenceContext並設定JNDI名稱來查找, 二是透過@PersistenceUnit注入EntityManagerFactory並用其取得EntityManager,前者的方式為 Container-Managed Entity,後者的方式則為Application-Managed EntityManager。
第一個方法若以 第一個 JPA(容器管理) 中的User實體為例,您可以如下撰寫Servlet:
- UserAdmin.java
package onlyfun.caterpillar;
import java.io.*;
import java.util.logging.*;
import javax.annotation.*;
import javax.naming.*;
import javax.persistence.*;
import javax.rmi.PortableRemoteObject;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.transaction.*;
@PersistenceContext(name="sample/EntityManager", unitName="sample")
public class UserAdmin extends HttpServlet {    
    @Resource 
    private UserTransaction ut;
    protected void processRequest(HttpServletRequest request, 
                                HttpServletResponse response)
                                    throws ServletException, IOException {
        
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        
        User user = new User();
        user.setName(name);
        user.setAge(new Long(Long.parseLong(age)));
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        EntityManager entityManager = null;
        try {
            InitialContext context = new InitialContext();
            Object obj = context.lookup(
                    "java:comp/env/sample/EntityManager");
            entityManager = (EntityManager) 
               PortableRemoteObject.narrow(obj, EntityManager.class);
            
            ut.begin();
            entityManager.persist(user);
            ut.commit();
        } catch (Exception ex) {
            Logger.getLogger(UserAdmin.class.getName())
                    .log(Level.SEVERE, null, ex);
        } finally { 
            entityManager.close();
            out.close();
        }
    } 
    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response)
                                  throws ServletException, IOException {
        processRequest(request, response);
    } 
    protected void doPost(HttpServletRequest request, 
                          HttpServletResponse response)
                                 throws ServletException, IOException {
        processRequest(request, response);
    }
}在您的Web應用程式可存取的Classpath路徑中(例如WEB-INF/classes下),要建立META-INF/persistence.xml:
- persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="sample" transaction-type="JTA">
    <jta-data-source>jdbc/sample</jta-data-source>
    <properties>
      <property name="toplink.ddl-generation" 
                value="drop-and-create-tables"/>
    </properties>
  </persistence-unit>
</persistence>@PersistenceContext的name名稱將作為JNDI查找名稱,從unitName設定得知,實際上查找到的 是<persistence-unit>中對應的sample定義,Servlet中使用JNDI查找name名稱以取得 EntityManager實例,並透過注入的UserTransaction啟用交易,在交易中進行持久化動作。
若不在類別上使用@PersistenceContext,您也可以在web.xml中加入以下的定義:
....
<persistence-context-ref>
<persistence-context-ref-name>
sample/EntityManager
</persistence-context-ref>
<persistence-unit-name>
sample
</persistence-unit-name>
</persistence-context-ref>
....
      
      <persistence-context-ref>
<persistence-context-ref-name>
sample/EntityManager
</persistence-context-ref>
<persistence-unit-name>
sample
</persistence-unit-name>
</persistence-context-ref>
....
第一個方法直接使用@PersistenceUnit注入EntityManagerFactory,例如:
- UserAdmin.java
package onlyfun.caterpillar;
import java.io.*;
import java.util.logging.*;
import javax.annotation.*;
import javax.persistence.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.transaction.*;
public class UserAdmin extends HttpServlet {    
    @PersistenceUnit(unitName="sample")
    private EntityManagerFactory emFactory;
    
    @Resource 
    private UserTransaction ut;
    protected void processRequest(HttpServletRequest request, 
                                HttpServletResponse response)
                                    throws ServletException, IOException {
        
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        
        User user = new User();
        user.setName(name);
        user.setAge(new Long(Long.parseLong(age)));
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        EntityManager entityManager = null;
        
        try {
            entityManager = emFactory.createEntityManager();
            
            ut.begin();
            entityManager.persist(user);
            ut.commit();
        } catch (Exception ex) {
            Logger.getLogger(UserAdmin.class.getName())
                    .log(Level.SEVERE, null, ex);
        } finally { 
            entityManager.close();
            out.close();
        }
    } 
    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response)
                                  throws ServletException, IOException {
        processRequest(request, response);
    } 
    protected void doPost(HttpServletRequest request, 
                          HttpServletResponse response)
                                 throws ServletException, IOException {
        processRequest(request, response);
    }
}類似於 第一個 JPA(單機客戶端) 中的例子,您從注入的EntityManagerFactory中建立EntityManager,之後利用其進行持久化物件或其它的操作。

