JPA EntityManager详解(二)
★ 提示 ★
|
虽然在目前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. }