★ 提示 ★
目前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. } |