JPA EntityManager详解(一)
持久化上下文(Persistence Contexts)的相关知识,内容包括如何从Java EE容器中创建EntityManager对象、如何从Java SE中创建EntityManager对象、持久化上下文与事务(Transction)的关系,以及实体管理器工厂(Entity Manager Factory)的相关内容。
通过本章的学习,读者将深入掌握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对象最为常用,例如下面代码所示。
- @Stateless
- public class CustomerService implements ICustomerService {
- @PersistenceContext(unitName = "jpaUnit")
- private EntityManager entityManager;
- public List<CustomerEO> findAllCustomers() {
- 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());
- }
- return result;
- }
- }
在使用此种方式创建EntityManager对象时,需要注意以下几个问题。
— @PersistenceContext注释中,其中unitName为persistence.xml文件中<persistence-unit>元素中的属性“name”的值,表示要初始化哪个持久化单元,如下所示。
- <persistence>
- <persistence-unit name="jpaUnit" transaction-type="JTA">
- </persistence-unit>
- </persistence>
— @PersistenceContext注释中还可以配置其他的设置,它的定义如下所示。
- @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
- public @interface PersistenceContext{
- String name() default "";
- String unitName() default "";
- PersistenceContextType type default TRANSACTION;
- PersistenceProperty[] properties() default {};
- }
— 其中PersistenceContextType可以设置创建EntityManager对象时,持久化上下文的作用范围,它的意义在于对有状态的Bean(Stateless Bean)可以跨事务操作实体。它主要有两种方式,定义如下所示。
- public enum PersistenceContextType {
- TRANSACTION,
- EXTENDED
- }
默认情况下使用TRANSACTION,有关TRANSACTION方式和EXTENDED方式创建EntityManager对象的异同,将在下文中详细讲述,这里读者简单了解一下即可。
11.1.3.2 通过JNDI的方式获得
如果指定了@PersistenceContext注释中的name值,则设置了持久化上下文的JNDI名称。通过SessionContext可以创建EntityManager对象。
例如,下面代码为通过JNDI方式获得EntityManager对象。
- @Stateless
- @PersistenceContext(name="jpa")
- public class CustomerService implements ICustomerService {
- @Resource
- SessionContext ctx;
- public List<CustomerEO> findAllCustomers() {
- EntityManager entityManager = (EntityManager) ctx.lookup("jpa");
- 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());
- }
- return result;
- }
- }
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对象的方法。
- @Stateless
- public class CustomerService implements ICustomerService {
- @PersistenceUnit(unitName="jpaUnit")
- private EntityManagerFactory emf;
- public List<CustomerEO> findAllCustomers() {
- /**创建EntityManager对象*/
- EntityManager em = emf.createEntityManager();
- Query query = em.createQuery("SELECT c FROM CustomerEO c");
- List<CustomerEO> result = query.getResultList();
- for (CustomerEO c : result) {
- System.out.println(c.getId()+","+c.getName());
- }
- /**关闭EntityManager */
- em.close();
- return result;
- }
- }
通过以上的EntityManager对象代码,可以总结出以下几个问题。
— 应用托管的EntityManager对象,要在代码中手动地创建和关闭,例如下面代码所示。
EntityManager em = emf.createEntityManager();
/**其他的业务逻辑*/
em.close();
这点正是与容器托管的EntityManager对象的最大不同之处。事实上,容器托管的EntityManager对象,它的创建和关闭是由容器负责管理的,所以不需要编写代码来控制。
— 应用托管的EntityManager对象,都是通EntityManagerFactory对象来创建的。在容器中可以通过使用注入@PersistenceUnit注释的方法实现,它的定义如下所示。
- @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
- public @interface PersistenceUnit{
- String name() default "";
- String unitName() default "";
- }
其中,属性unitName为persistence.xml文件中<persistence-unit>元素中的属性“name”的值,表示要初始化哪个持久化单元,与@PersistenceContext注释中unitName属性相同。
11.1.4.2 Web容器中获得
在
Web容器中,EntityManagerFactory对象也可以通过使用注入@PersistenceUnit注释获得。例如,下面代码为在
Servlet中,获得应用托管的EntityManager对象的方法。
/syntaxhighlighter/clipboard_new.swf">
- public class TestServlet extends HttpServlet {
- @PersistenceUnit(unitName = "jpaUnit")
- 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();
- }
JPA EntityManager详解(一)的更多相关文章
- JPA EntityManager详解
EntityManager是JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的数据存储.其接口如下: public interface EntityManager ...
- spring+springMVC+JPA配置详解(使用缓存框架ehcache)
SpringMVC是越来越火,自己也弄一个Spring+SpringMVC+JPA的简单框架. 1.搭建环境. 1)下载Spring3.1.2的发布包:Hibernate4.1.7的发布包(没有使用h ...
- Spring、SpringMVC、SpringData + JPA 整合详解
原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7759874.html ------------------------------------ ...
- Spring Data JPA实体详解
1. Spring Data JPA实体概述 JPA提供了一种简单高效的方式来管理Java对象(POJO)到关系数据库的映射,此类Java对象称为JPA实体或简称实体.实体通常与底层数据库中的单个关系 ...
- spring data jpa使用详解
https://blog.csdn.net/liuchuanhong1/article/details/52042477 使用Spring data JPA开发已经有一段时间了,这期间学习了一些东西, ...
- Jpa使用详解
目录 ORM思想 1.ORM概述 2.为什么要使用ORM 3.常见的ORM框架 JPA简介 1.JPA概述 2.JPA的优势 3.JPA与hibernate的关系 JPA入门案例 1.搭建开发环境 常 ...
- JPA 注解详解
@Entity --声明为一个实体类bean @Table (name= "promotion_info" ) --为实体bean映射指定表(表名="promotion_ ...
- SpringBoot05 数据操作02 -> JPA接口详解
概览 JpaRepository 继承 PagingAndSortingRepository 继承 CrudRepository 继承 Repository 1 Repository 这是一个空接口, ...
- SpringBoot JPA注解详解
1.@OneToOne 2.@OneToManytargetEntity: 默认关联的实体类型.如果集合类中指定了具体类型了,不需要使用targetEntity.否则需要targetEntity指定C ...
随机推荐
- 8、web入门回顾/ Http
1 web入门回顾 web入门 1)web服务软件作用: 把本地资源共享给外部访问 2)tomcat服务器基本操作 : 启动: %tomcat%/bin/startup.bat 关闭: % ...
- canvas 动画
1.随机产生形状,做360度运转,带有一个开始开始按钮一个停止按钮 var canvas=$('.mycanvas'); canvas.attr("width",500);//$( ...
- 微信支付 APP 支付方式的服务器端处理程序
对于微信的APP的支付,客户服务说只能通过微信开放平台申请.后来在公众帐号确实发现了证据: 微信支付在申请的时候就比较严(麻烦),对服务类的一些支付,本来商品就是虚拟的,所以需要将商品描述的比较详细 ...
- Cocos2dx框架常用单词(一)
收集了一些Cocos2dx里面主要单词的翻译. Toggle:切换Finite:有限Instant:瞬时interval:间隔Flip:翻转place:座位,放置Target:目标reverse:反向 ...
- Oracle绑定变量
select * from table where id = ? 类似于上面这样的sql,如果不用绑定变量,每次执行时Oracle会认为是不同的sql,会在每次执行时生成一遍执行计划,而执行计划的生成 ...
- common-pool2 使用
common-pool2提供了3中对象池管理方式,它们的使用方式基本一样,这里以GenericObjectPool对象池为例介绍其使用方式,一般实现自己的对象池需要经过2个步骤 1.实现PooledO ...
- AB串(上帝都不会,我就没救了)
[题目分析] 设答案的长度为m,
- IOS时间戳
什么是时间戳? 时间戳(timestamp),通常是一个字符序列,唯一地标识某一刻的时间.数字时间戳技术是数字签名技术一种变种的应用. 思考:简单来讲就是根据文件hash加密后生成的摘要和时间生成的时 ...
- CodeForces 670D2 Magic Powder 二分
D2. Magic Powder - 2 The term of this problem is the same as the previous one, the only exception — ...
- android 串口调试
在usb调试过程中,都会选择串口查看log,更希望在串口中输入命令查看相关状态.但是一般情况下串口调试时 进程用户是shell,即使你在adb shell下是root用户. 暴力方法是在 adroid ...