首页 > 其他分享 >JPA EntityManager详解

JPA EntityManager详解

时间:2023-08-30 11:31:51浏览次数:46  
标签:容器 EntityManager Web JPA 托管 EJB 对象 详解


JPA EntityManager详解(一)



 
通过本章的学习,读者将深入掌握JPA中有关持久化上下文、事务处理的相关知识,从而能够更加深入地应用JPA。  


11.1 获得EntityManager对象  

那么如何获得EntityManager对象呢?这又是JPA中另外一个很重要的问题。  


11.1.1  Java EE环境与J2SE环境  

在详细讲述EntityManager对象之前,读者首先要分清楚两个概念,即Java EE环境与J2SE环境。因为在本章后面的学习中要经常提到这两个概念,所以读者一定要先理解它们,为以后的学习打好基础。  


— Java EE环境,包括EJB容器和Web容器。  

(1)Web容器:只运行Web应用的容器,例如Tomcat就是开源的Web容器,它可以运行JSP、Servlet等。  

(2)EJB容器:运行在EJB组件的容器,提供EJB组件的状态管理、事务管理、线程管理、远程数据资源访问、连接管理和安全性管理等系统级服务。例如JBoss为EJB容器和Web容器(Web容器是集成了Tomcat)结合。  

部署在EJB容器中的JAR包都可以认为是运行在EJB容器中。但JBoss中的Web应用,比如war包中的类就不是运行在EJB容器中,而是运行在Web容器中。  

— J2SE环境  

最普通Java运行环境,例如一个HelloWorld的Java程序就是运行在J2SE的环境中,通常使用main入口方法作为程序启动的触发。  

如图11-1所示,它说明了Java EE与J2SE环境的关系。  

11.1.2  两种类型的EntityManager对象  

根据EntityManager对象的管理方式,可以有以下两种类型。  

— 容器托管的(container-managed)EntityManager对象  

容器托管的EntityManager对象最简单,程序员不需要考虑EntityManager连接的释放,以及事务等复杂的问题,所有这些都交 给容器去管理。容器托管的EntityManager对象必须在EJB容器中运行,而不能在Web容器和J2SE的环境中运行。本书前面讲述的 EntityManager对象都是通过注入 @PersistenceContext注释来获得的,其实,这种获得EntityManager对象的方式就是容器托管的。  

— 应用托管的(application-managed)EntityManager对象  

应用托管的EntityManager对象,程序员需要手动地控制它的释放和连接、手动地控制事务等。但这种获得应用托管的 EntityManager对象的方式,不仅可以在EJB容器中应用,也可以使 JPA脱离EJB容器,而与任何的Java环境集成,比如说Web容器、J2SE环境等。所以从某种角度上来说,这种方式是JPA能够独立于EJB环境运 行的基础。  

理想状态下,最好是选用容器托管的EntityManager对象的方式,但在特殊的环境下,还是需要使用应用托管的EntityManager对象这种方式。  

正是因为应用托管的EntityManager对象的连接释放、事务控制比较复杂,所以在使用时涉及的相关内容比较多,这些内容将在本章后面部分详细讲述,这里读者应对两种方式有一个大致的了解,两种EntityManager对象类型的比较如表11-1所示。  

表11-1  容器托管与应用托管的EntityManager对象对比  

比较内容  

容器托管的(container-managed)EntityManager对象  

应用托管的(application-managed)EntityManager对象  

获得方式  

两种方式:1 @PersistenceContex注入 2 JNDI获得  

EntityManagerFactory创建  

支持事务  

JTA  

JTA、RESOURCE_LOCAL  

运行环境  

EJB容器  

EJB容器、Web容器、J2SE环境  

11.1.3  容器托管的(container-managed)EntityManager对象  

容器托管的EntityManager对象只能运行在EJB容器中。所以可以这样理解,只有在EJB-JAR包中,才可以获得容器托管的EntityManager对象,否则只能获得应用托管的EntityManager对象。  

在EJB容器中获得EntityManager对象主要有两种方式,即@PersistenceContext注释注入和JNDI方式获得。  

11.1.3.1  通过@PersistenceContext注释注入  

这种方式获得EntityManager对象最为常用,例如下面代码所示。  

1. @Stateless
2.   
3. public class CustomerService implements
4.   
5. @PersistenceContext(unitName = "jpaUnit")  
6.   
7. private
8.   
9. public
10.   
11. "SELECT c FROM CustomerEO c");  
12.   
13.         List<CustomerEO> result = query.getResultList();  
14.   
15. for
16.   
17. ","+c.getName());  
18.   
19.         }  
20.   
21. return
22.   
23.     }  
24.   
25. }




在使用此种方式创建EntityManager对象时,需要注意以下几个问题。

 


— @PersistenceContext注释中,其中unitName为persistence.xml文件中<persistence-unit>元素中的属性“name”的值,表示要初始化哪个持久化单元,如下所示。

 




Xml代码


1. <persistence>
2.   
3. <persistence-unit name="jpaUnit" transaction-type="JTA">
4.   
5. </persistence-unit>
6.   
7. </persistence>



— @PersistenceContext注释中还可以配置其他的设置,它的定义如下所示。

 




Java代码


1. @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)   
2.   
3. public @interface
4.   
5. default "";  
6.   
7. default "";  
8.   
9. default
10.   
11. default
12.   
13. }


— 其中PersistenceContextType可以设置创建EntityManager对象时,持久化上下文的作用范围,它的意义在于对有状态的Bean(Stateless Bean)可以跨事务操作实体。它主要有两种方式,定义如下所示。

 



Java代码


1. public enum
2.   
3.     TRANSACTION,  
4.   
5.     EXTENDED  
6.   
7. }



默认情况下使用TRANSACTION,有关TRANSACTION方式和EXTENDED方式创建EntityManager对象的异同,将在下文中详细讲述,这里读者简单了解一下即可。

 


11.1.3.2  通过JNDI的方式获得

 


如果指定了@PersistenceContext注释中的name值,则设置了持久化上下文的JNDI名称。通过SessionContext可以创建EntityManager对象。

 


例如,下面代码为通过JNDI方式获得EntityManager对象。

 

1. @Stateless
2.   
3. @PersistenceContext(name="jpa")   
4.   
5. public class CustomerService implements
6.   
7. @Resource
8.   
9.     SessionContext ctx;  
10.   
11. public
12.   
13. "jpa");  
14.   
15. "SELECT c FROM CustomerEO c");  
16.   
17.         List<CustomerEO> result = query.getResultList();  
18.   
19. for
20.   
21. ","+c.getName());  
22.   
23.         }  
24.   
25. return
26.   
27.     }  
28.   
29. }




11.1.4  应用托管的(application-managed)EntityManager对象

 


应用托管的EntityManager对象,不仅可以在Java EE环境中获得,也可以应用在J2SE的环境中。但无论是在什么情况下获得的EntityManager对象,都是通过实体管理器工厂 (EntityManagerFactory)对象创建的。所以如何获得应用托管的EntityManager对象关键是 EntityManagerFactory对象如何获得。

 


下面就分别讲述在EJB容器、Web容器和J2SE环境中如何获得EntityManagerFactory对象。

 


11.1.4.1  EJB容器中获得

 


在EJB容器中,EntityManagerFactory对象可以通过使用注入@PersistenceUnit注释获得,例如下面代码为在EJB容器中,获得应用托管的EntityManager对象的方法。

 

1. @Stateless
2.   
3. public class CustomerService implements
4.   
5. @PersistenceUnit(unitName="jpaUnit")  
6.   
7. private
8.   
9. public
10.   
11. /**创建EntityManager对象*/
12.   
13.         EntityManager em = emf.createEntityManager();  
14.   
15. "SELECT c FROM CustomerEO c");  
16.   
17.         List<CustomerEO> result = query.getResultList();  
18.   
19. for
20.   
21. ","+c.getName());  
22.   
23.         }  
24.   
25. /**关闭EntityManager */
26.   
27.         em.close();  
28.   
29. return
30.   
31.     }  
32.   
33. }



通过以上的EntityManager对象代码,可以总结出以下几个问题。

 


— 应用托管的EntityManager对象,要在代码中手动地创建和关闭,例如下面代码所示。

 


EntityManager em = emf.createEntityManager();

 


/**其他的业务逻辑*/

 


em.close();

 


这点正是与容器托管的EntityManager对象的最大不同之处。事实上,容器托管的EntityManager对象,它的创建和关闭是由容器负责管理的,所以不需要编写代码来控制。

 


— 应用托管的EntityManager对象,都是通EntityManagerFactory对象来创建的。在容器中可以通过使用注入@PersistenceUnit注释的方法实现,它的定义如下所示。

 

1. @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)   
2.   
3. public @interface
4.   
5. default "";  
6.   
7. default "";  
8.   
9. }


其中,属性unitName为persistence.xml文件中<persistence-unit>元素中的属性“name”的值,表示要初始化哪个持久化单元,与@PersistenceContext注释中unitName属性相同。

 


11.1.4.2  Web容器中获得

 


在Web容器中,EntityManagerFactory对象也可以通过使用注入@PersistenceUnit注释获得。例如,下面代码为在 Servlet中,获得应用托管的EntityManager对象的方法。 /syntaxhighlighter/clipboard_new.swf">



 


1. public class TestServlet extends
2.   
3. @PersistenceUnit(unitName = "jpaUnit")  
4.   
5. private
6.   
7. public
8.   
9. super();  
10.   
11.     }  
12.   
13. public void
14.   
15. throws
16.   
17.         doPost(request, response);  
18.   
19.     }  
20.   
21. public void
22.   
23. throws
24.   
25. "text/html");  
26.   
27.         PrintWriter out = response.getWriter();  
28.   
29. "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional //EN\">");  
30.   
31. "<HTML>");  
32.   
33. "  <HEAD><TITLE>A Servlet</TITLE></HEAD>");  
34.   
35. "  <BODY>");  
36.   
37. if (emf != null) {  
38.   
39. /**创建EntityManager 对象*/
40.   
41.             EntityManager entityManager = emf.createEntityManager();  
42.   
43. try
44.   
45.                 Query query = entityManager  
46.   
47. "SELECT c FROM CustomerEO c");  
48.   
49.                 List<CustomerEO> result = query.getResultList();  
50.   
51. for
52.   
53. ","
54.   
55.                 }  
56.   
57. finally
58.   
59. /**关闭EntityManager*/
60.   
61.                 entityManager.close();  
62.   
63.             }  
64.   
65.         }  
66.   
67. "  </BODY>");  
68.   
69. "</HTML>");  
70.   
71.         out.flush();  
72.   
73.         out.close();  
74.   
75.     }  
76.   
77. }


标签:容器,EntityManager,Web,JPA,托管,EJB,对象,详解
From: https://blog.51cto.com/u_16240770/7289258

相关文章

  • html5之拖放详解
    拖放是一种常见的特性,即抓取对象以后拖到另一个位置。在HTML5中,拖放是标准的一部分,任何元素都能够拖放。InternetExplorer9、Firefox、Opera12、Chrome以及Safari5支持拖放。1.drggable属性如果网页元素的draggable元素为true,这个元素就是可以拖动的。<div draggable......
  • 【性能测试】ulimit命令说明与用法-详解
    目录1、ulimit命令与显示说明2.常用操作-ulimit是临时修改-程序要使用配置得重启3、永久修改的话修改配置文件正文1、ulimit命令与显示说明ulimit命令是Linux系统的内建功能,它具有一套参数集,用于控制shell进程及其所创进程的资源使用限制。它主要用于设置用户和系......
  • 深入详解ThreadLocal
    本文已收录至GitHub,推荐阅读......
  • Windows环境 python手动安装三方库详解
    当运行pip安装三方库时,无法正常安装,可以自己手动安装一下详解:1、首先找到需要下载的三方库的安装包---三方库下载地址:https://pypi.org/project  打开网址搜索需要下载的三方库的安装包,我是以“locust”为例找到需要下载的三方库,点击进去找到对应的版本下载对应的****......
  • 一文详解:人工智能AI技术在智慧矿山安全监管平台建设中的应用及意义
    智慧矿山是这几年的热点话题,伴随着国家对矿业行业的不断重视和扶持,推动矿山智慧化升级改造、保障安全生产也成为当前的重要任务。“智慧矿山”的建设,需要集成应用各类传感感知、信息通讯、自动控制、智能决策等先进信息化技术,能够显著提升矿山生产效率与安全水平,通过先进装备和信......
  • win11安装redis步骤详解
    1、下载及解压    https://www.runoob.com/redis/redis-install.html 2、启动redis 以管理员身份,打开一个cmd窗口, 切换目录到redis安装目录下执行:redis-server.exeredis.windows.conf如果不制定配置文件,那么默认是不需要密码的后面的那个redis.windows.co......
  • Gson与FastJson详解
    Gson与FastJson详解Java与JSON做什么?将Java中的对象快速的转换为JSON格式的字符串.将JSON格式的字符串,转换为Java的对象.Gson将对象转换为JSON字符串转换JSON字符串的步骤:引入JAR包在需要转换JSON字符串的位置编写如下代码即可:Stringjson=newGson().toJSON(要转换的对象......
  • FAST协议详解3 可null(空)类型
    一、概述所谓可null、可空,其实是一个特性的两个方面,某些情况下,我们不需要传递某个字段的值,则可以将该字段“空”起来,不赋值,则接收方在收到该字段时会自动解析为null值。所以空是对于发送方而言,而null则是对于接收方而言,但FAST流中并不会因为没有对该字段赋值就可以节省下一个字节......
  • Gson与FastJson详解
    Gson与FastJson详解Java与JSON做什么?将Java中的对象快速的转换为JSON格式的字符串.将JSON格式的字符串,转换为Java的对象.Gson将对象转换为JSON字符串转换JSON字符串的步骤:引入JAR包在需要转换JSON字符串的位置编写如下代码即可:Stringjson=newGson().toJSON(......
  • 智能指针详解
    文章目录一、智能指针背后的设计思想二、普通指针存在的问题三、shared_ptr类1、make_shared函数2、shared_ptr的拷贝和赋值3、shared_ptr自动销毁所管理的对象4、使用动态内存的原因:5、使用shared_ptr的一个例子:四、shared_ptr的实现和循环引用问题五、weak_ptr类1、weak_ptr详解......