| 
 ★ 提示 ★
  目前JBoss 4.2集成了的Tomcat版本为5.5,但Tomcat 6.0以后的版本中才支持使用注释,所以如果将本例中Servlet运行在JBoss 4.2中,并不能获得EntityManagerFactory对象;但在符合J2EE 5.0的服务器中,这样运行是可以的。
  虽然在目前JBoss 4.2版本中不支持使用注释,但可以通过另一种方式来获得应用托管的EntityManager对象。代码如下所示。
  1. public class TestServlet extends HttpServlet {   2.    3.     private EntityManagerFactory emf;   4.    5.     public TestServlet() {   6.    7.         super();   8.    9.     }   10.    11.     public void doGet(HttpServletRequest request, HttpServletResponse response)   12.    13.             throws ServletException, IOException {   14.    15.         doPost(request, response);   16.    17.     }   18.    19.     public void doPost(HttpServletRequest request, HttpServletResponse response)   20.    21.             throws ServletException, IOException {   22.    23.         response.setContentType("text/html");   24.    25.         PrintWriter out = response.getWriter();   26.    27.         out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional //EN\">");   28.    29.         out.println("<HTML>");   30.    31.         out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");   32.    33.         out.println("  <BODY>");   34.    35.         if (emf != null) {   36.    37.             /**创建EntityManager 对象*/   38.    39.             EntityManager entityManager = emf.createEntityManager();   40.    41.             try {   42.    43.                 Query query = entityManager   44.    45.                         .createQuery("SELECT c FROM CustomerEO c");   46.    47.                 List<CustomerEO> result = query.getResultList();   48.    49.                 for (CustomerEO c : result) {   50.    51.                     System.out.println(c.getId() + "," + c.getName());   52.    53.                 }   54.    55.             } finally {   56.    57.                 /**关闭EntityManager*/   58.    59.                 entityManager.close();   60.    61.             }   62.    63.         }   64.    65.         out.println("  </BODY>");   66.    67.         out.println("</HTML>");   68.    69.         out.flush();   70.    71.         out.close();   72.    73.     }   74.    75.     /**Servlet初始化时,创建EntityManagerFactory 对象*/   76.    77.     public void init() throws ServletException {   78.    79.         if (emf == null) {   80.    81.             emf = Persistence.createEntityManagerFactory("jpaUnit");   82.    83.         }   84.    85.     }   86.    87.     /**Servlet销毁时,关闭EntityManagerFactory对象*/   88.    89.     public void destroy() {   90.    91.         if (emf.isOpen())   92.    93.             emf.close();   94.    95.     }   96.    97. }  
  public class TestServlet extends HttpServlet {
  private EntityManagerFactory emf;
  public TestServlet() {
  super();
  }
  public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
  doPost(request, response);
  }
  public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional //EN\">");
  out.println("<HTML>");
  out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
  out.println("  <BODY>");
  if (emf != null) {
  /**创建EntityManager 对象*/
  EntityManager entityManager = emf.createEntityManager();
  try {
  Query query = entityManager
  .createQuery("SELECT c FROM CustomerEO c");
  List<CustomerEO> result = query.getResultList();
  for (CustomerEO c : result) {
  System.out.println(c.getId() + "," + c.getName());
  }
  } finally {
  /**关闭EntityManager*/
  entityManager.close();
  }
  }
  out.println("  </BODY>");
  out.println("</HTML>");
  out.flush();
  out.close();
  }
  /**Servlet初始化时,创建EntityManagerFactory 对象*/
  public void init() throws ServletException {
  if (emf == null) {
  emf = Persistence.createEntityManagerFactory("jpaUnit");
  }
  }
  /**Servlet销毁时,关闭EntityManagerFactory对象*/
  public void destroy() {
  if (emf.isOpen())
  emf.close();
  }
  }
 
 
  使用这种方式创建EntityManagerFactory对象需要注意以下几个问题。
  可以看到,这里的EntityManagerFactory对象不是通过注入获得的,而是通过Persistence类中的静态方法createEntityManagerFactory来创建的。
  — 正因为EntityManagerFactory对象是手动创建的,所以在不再使用时,一定要调用close()方法手动关闭。
  11.1.4.3  J2SE环境中获得
  在J2SE环境中,获得应用托管的EntityManager对象只能通过手动创建的方式,而不能使用注释的方式,与Web容器中不使用注释的方法相同,都是通过Persistence类中createEntityManagerFactory来创建的。
  例如,下面代码为J2SE环境中获得应用托管EntityManager对象的方法。
  1. public class CustomerClient {   2.    3.     public static void main(String[] args) {   4.    5.         /** 创建EntityManagerFactory对象 */   6.    7.         EntityManagerFactory emf = Persistence   8.    9.                 .createEntityManagerFactory("jpaUnit");   10.    11.         /** 创建entityManager对象 */   12.    13.         EntityManager entityManager = emf.createEntityManager();   14.    15.         Query query = entityManager.createQuery("SELECT c FROM CustomerEO c");   16.    17.         List<CustomerEO> result = query.getResultList();   18.    19.         for (CustomerEO c : result) {   20.    21.             System.out.println(c.getId() + "," + c.getName());   22.    23.         }   24.    25.         /** 关闭entityManager对象 */   26.    27.         entityManager.close();   28.    29.         /** 关闭EntityManagerFactory对象 */   30.    31.         emf.close();   32.    33.     }   34.    35. }  
  public class CustomerClient {
  public static void main(String[] args) {
  /** 创建EntityManagerFactory对象 */
  EntityManagerFactory emf = Persistence
  .createEntityManagerFactory("jpaUnit");
  /** 创建entityManager对象 */
  EntityManager entityManager = emf.createEntityManager();
  Query query = entityManager.createQuery("SELECT c FROM CustomerEO c");
  List<CustomerEO> result = query.getResultList();
  for (CustomerEO c : result) {
  System.out.println(c.getId() + "," + c.getName());
  }
  /** 关闭entityManager对象 */
  entityManager.close();
  /** 关闭EntityManagerFactory对象 */
  emf.close();
  }
  }
 
  但是,在J2SE环境中使用JPA需要将实现的JPA的第三方类包和数据库的驱动包,设置到当前的运行环境下。
  例如,在Eclipse中创建一个Java项目,需要将JPA实现者的类库(这里以Hibernate为例)和MySQL的数据库连接包添加到构建路径中,如图11-2所示。
  11.1.5  ThreadLocal的使用
  对于在Web容器中使用EntityManager对象,这里需要做一些改进,才能更安全。读者应该了解,Servlet是非线程安全的,所以需要改变获得EntityManager对象的方式,这里笔者建议使用ThreadLocal类。
  ThreadLocal就是为每一个使用某变量的线程都提供一个该变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其他线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有一个该变量,这就解决了Servlet非线程安全的问题。
  首先编写一个EntityManagerHelper类,代码如下所示。
  1. public class EntityManagerHelper {   2.    3.       4.    5.     private static final EntityManagerFactory emf;   6.    7.     private static final ThreadLocal<EntityManager> threadLocal;   8.    9.       10.    11.     /**初始化*/   12.    13.     static {   14.    15.         emf = Persistence.createEntityManagerFactory("jpaUnit");          16.    17.         threadLocal = new ThreadLocal<EntityManager>();   18.    19.     }   20.    21.       22.    23.     /**通过threadLocal 获得EntityManager 对象*/   24.    25.     public static EntityManager getEntityManager() {   26.    27.         EntityManager manager = threadLocal.get();        28.    29.         if (manager == null || !manager.isOpen()) {   30.    31.             manager = emf.createEntityManager();   32.    33.             threadLocal.set(manager);   34.    35.         }   36.    37.         return manager;   38.    39.     }   40.    41.       42.    43.     /**关闭EntityManager 对象*/   44.    45.     public static void closeEntityManager() {   46.    47.         EntityManager em = threadLocal.get();   48.    49.         threadLocal.set(null);   50.    51.         if (em != null) em.close();   52.    53.     }   54.    55.       56.    57.     public static void beginTransaction() {   58.    59.     getEntityManager().getTransaction().begin();   60.    61.     }   62.    63.       64.    65.     public static void commit() {   66.    67.     getEntityManager().getTransaction().commit();   68.    69.     }    70.    71.       72.    73.     public static Query createQuery(String query) {   74.    75.         return getEntityManager().createQuery(query);   76.    77.     }   78.    79.       80.    81. }  
  public class EntityManagerHelper {
 
 
  private static final EntityManagerFactory emf;
  private static final ThreadLocal<EntityManager> threadLocal;
 
 
  /**初始化*/
  static {
  emf = Persistence.createEntityManagerFactory("jpaUnit");       
  threadLocal = new ThreadLocal<EntityManager>();
  }
 
 
  /**通过threadLocal 获得EntityManager 对象*/
  public static EntityManager getEntityManager() {
  EntityManager manager = threadLocal.get();     
  if (manager == null || !manager.isOpen()) {
  manager = emf.createEntityManager();
  threadLocal.set(manager);
  }
  return manager;
  }
 
 
  /**关闭EntityManager 对象*/
  public static void closeEntityManager() {
  EntityManager em = threadLocal.get();
  threadLocal.set(null);
  if (em != null) em.close();
  }
 
 
  public static void beginTransaction() {
  getEntityManager().getTransaction().begin();
  }
 
 
  public static void commit() {
  getEntityManager().getTransaction().commit();
  } 
 
 
  public static Query createQuery(String query) {
  return getEntityManager().createQuery(query);
  }
 
 
  }
 
 
  这样经过改进后,在Servlet中创建EntityManager对象的方法修改为如下所示。
  1. public class TestServlet extends HttpServlet {   2.    3.     public TestServlet() {   4.    5.         super();   6.    7.     }   8.    9.     public void doPost(HttpServletRequest request, HttpServletResponse response)   10.    11.             throws ServletException, IOException {   12.    13.             EntityManager entityManager = EntityManagerHelper.getEntityManager();   14.    15.             try {   16.    17.                 Query query = entityManager   18.    19.                         .createQuery("SELECT c FROM CustomerEO c");   20.    21.                 List<CustomerEO> result = query.getResultList();   22.    23.                 for (CustomerEO c : result) {   24.    25.                     System.out.println(c.getId() + "," + c.getName());   26.    27.                 }   28.    29.             } finally {   30.    31.                 /**关闭EntityManager*/   32.    33.                 EntityManagerHelper.closeEntityManager();   34.    35.             }   36.    37.     }   38.    39. }   |