EntityManager方法简介

EntityManager 是用来对实体Bean 进行操作的辅助类。他可以用来产生/删除持久化的实体Bean,通过主键查找实体bean,也可以通过EJB3 QL 语言查找满足条件的实体Bean。实体Bean 被EntityManager 管理时,EntityManager跟踪他的状态改变,在任何决定更新实体Bean 的时候便会把发生改变的值同步到数据库中。当实体Bean 从EntityManager 分离后,他是不受管理的,EntityManager 无法跟踪他的任何状态改变。EntityManager 的获取前面已经介绍过,可以通过@PersistenceContext 注释由EJB 容器动态注入,例:

@PersistenceContext(unitName="foshanshop")

EntityManager em;

EntityManager常用方法:

1.Entity的获取

   find(*.class,ID) :若实体Bean不存在,则返回null

   getReference(*,class,ID) :若实体Bean不存在,则抛出javax.persistence.EntityNotFoundException,另,不保 证                                            实体Bean 已被初始化

   注意:若*.class不是Entity Bean的话,都会引发IllegalArgumentException

2.persist() :添加实体Bean

3.更新实体Bean :当实体正在被容器管理时,你可以调用实体的set 方法对数据进行修改,在容器决定flush 时,更新的数据才会同步到数据库。如果你希望修改后的数据实时同步到数据库,你可以执行EntityManager.flush()方法。

4.merge () :是在实体Bean 已经脱离了EntityManager 的管理时使用,当容器决定flush 时,数据将会同步到数据库中,执行em.merge(Object obj)方法时,容器的工作规则:

(1).如果此时容器中已经存在一个受容器管理的具有相同ID 的Object实例,容器将会把参数obj的内容拷贝进这个受管理的实例,merge()方法返回受管理的实例,但参数obj仍然是分离的不受管理的。容器在决定Flush时把实例同步到数据库中。

(2).容器中不存在具有相同ID 的Object实例。容器根据传进的obj参数Copy 出一个受容器管理的Object实例,同时merge()方法会返回出这个受管理的实例,但参数obj仍然是分离的不受管理的。容器在决定Flush时把 实例同步到数据库中。如果传递进merge ()方法的参数不是实体Bean,会引发一个IllegalArgumentException

5.Remove() :删除对象

6.createQuery() 返回Query对象,以执行JPQL语句

7.createNativeQuery() 返回Query对象,以执行SQL语句

8.refresh() 刷新实体Bean,以得到对新对象 (幽雅的获取最新对象方法)

9.contains() 检测实体当前是否被管理中

   该方法使用一个实体作为参数,如果这个实体对象当前正被持久化内容管理,返回值为true,否则为false

10.clear() 分离所有当前正在被管理的实体

     在处理大量实体的时候,如果你不把已经处理过的实体从EntityManager 中分离出来,将会消耗你大量的内存。调用EntityManager 的clear()方法后,所有正在被管理的实体将会从持久化内容中分离出来。

有一点需要说明下,在事务没有提交前(事务默认在调用堆栈的最后提交,如:方法的返回),如果调用clear()方法,之前对实体所作的任何改变将会掉失,所以建议你在调用clear()方法之前先调用flush()方法保存更改

11. flush() 将实体的改变立刻刷新到数据库中

当实体管理器对象在一个session bean 中使用时,它是和服务器的事务上下文绑定的。实体管理器在服务器的事务提交时提交并且同步它的内容。在一个session bean 中,服务器的事务默认地会在调用堆栈的最后提交(如:方法的返回)

12.javax.persistence.FlushModeType 实体Bean管理器的Flush模式

     FlushModeType.COMMIT   :刷新只有在事务提交时才发生,使用场合:在大量更新数据的过程中存在查询语句(除了find()和getreference()查询)的执行

     FlushModeType.AUTO :(默认模式)刷新在查询语句执行前(除了find()和getreference()查询)或事务提交时才发   生,使用场合:在大量更新数据的过程中没有任何查询语句(除了find()和getreference()查询)的执行。

JDBC 驱动跟数据库交互的次数。JDBC 性能最大的增进是减少JDBC 驱动与数据库之间的网络通讯FlushModeType.COMMIT 模式使更新只在一次的网络交互中完成,而FlushModeType.AUTO 模式可能需要多次交互(触发了多少次Flush 就产生了多少次网络交互)

设置:entityManager.setFlushMode(FlushModeType.COMMIT);

13.getDelegate( )   获取持久化实现者的引用

     用过getDelegate( )方法,你可以获取EntityManager 持久化实现者的引用,如Jboss EJB3 的持久化产品采用Hibernate,可以通过getDelegate( ) 方法获取对他的访问,如:

@PersistenceContext

protected EntityManager em;

HibernateEntityManager manager = (HibernateEntityManager)em.getDelegate();

获得对Hibernate 的引用后,可以直接面对Hibernate 进行编码,不过这种方法并不可取,强烈建议不要使用.在Weblogic 中,你也可以通过此方法获取对Kodo 的访问

另:映射的表名或列名与数据库保留字同名时的处理

     将表名加标式符,例如:在Mysql下,用'order',或在sqlserver下用[TableName],但这样做不适合程序移植

============================================

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对象最为常用,例如下面代码所示。

  1. @Stateless  
  2.   
  3. public class CustomerService implements ICustomerService {  
  4.   
  5.     @PersistenceContext(unitName = "jpaUnit")  
  6.   
  7.     private EntityManager entityManager;  
  8.   
  9.     public List<CustomerEO> findAllCustomers() {  
  10.   
  11.         Query query = entityManager.createQuery("SELECT c FROM CustomerEO c");  
  12.   
  13.         List<CustomerEO> result = query.getResultList();  
  14.   
  15.         for (CustomerEO c : result) {  
  16.   
  17.             System.out.println(c.getId()+","+c.getName());  
  18.   
  19.         }  
  20.   
  21.         return result;  
  22.   
  23.     }  
  24.   
  25. }  
@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”的值,表示要初始化哪个持久化单元,如下所示。

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

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

Java代码
  1. @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)  
  2.   
  3. public @interface PersistenceContext{  
  4.   
  5.     String name() default "";  
  6.   
  7.     String unitName() default "";  
  8.   
  9.     PersistenceContextType type default TRANSACTION;  
  10.   
  11.     PersistenceProperty[] properties() default {};  
  12.   
  13. }  
@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)可以跨事务操作实体。它主要有两种方式,定义如下所示。
Java代码
  1. public enum PersistenceContextType {  
  2.   
  3.     TRANSACTION,  
  4.   
  5.     EXTENDED  
  6.   
  7. }  
public enum PersistenceContextType { TRANSACTION, EXTENDED }

默认情况下使用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 ICustomerService {  
  6.   
  7.     @Resource  
  8.   
  9.     SessionContext ctx;  
  10.   
  11.     public List<CustomerEO> findAllCustomers() {  
  12.   
  13.         EntityManager entityManager = (EntityManager) ctx.lookup("jpa");  
  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.         return result;  
  26.   
  27.     }  
  28.   
  29. }  
@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对象的方法。

  1. @Stateless  
  2.   
  3. public class CustomerService implements ICustomerService {  
  4.   
  5.     @PersistenceUnit(unitName="jpaUnit")  
  6.   
  7.     private EntityManagerFactory emf;  
  8.   
  9.     public List<CustomerEO> findAllCustomers() {  
  10.   
  11.         /**创建EntityManager对象*/  
  12.   
  13.         EntityManager em = emf.createEntityManager();  
  14.   
  15.         Query query = em.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.         em.close();  
  28.   
  29.         return result;  
  30.   
  31.     }  
  32.   
  33. }  
@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注释的方法实现,它的定义如下所示。

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


其中,属性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 HttpServlet {  
  2.   
  3.     @PersistenceUnit(unitName = "jpaUnit")  
  4.   
  5.     private EntityManagerFactory emf;  
  6.   
  7.     public TestServlet() {  
  8.   
  9.         super();  
  10.   
  11.     }  
  12.   
  13.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  14.   
  15.             throws ServletException, IOException {  
  16.   
  17.         doPost(request, response);  
  18.   
  19.     }  
  20.   
  21.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  22.   
  23.             throws ServletException, IOException {  
  24.   
  25.         response.setContentType("text/html");  
  26.   
  27.         PrintWriter out = response.getWriter();  
  28.   
  29.         out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional //EN\">");  
  30.   
  31.         out.println("<HTML>");  
  32.   
  33.         out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");  
  34.   
  35.         out.println("  <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.                         .createQuery("SELECT c FROM CustomerEO c");  
  48.   
  49.                 List<CustomerEO> result = query.getResultList();  
  50.   
  51.                 for (CustomerEO c : result) {  
  52.   
  53.                     System.out.println(c.getId() + "," + c.getName());  
  54.   
  55.                 }  
  56.   
  57.             } finally {  
  58.   
  59.                 /**关闭EntityManager*/  
  60.   
  61.                 entityManager.close();  
  62.   
  63.             }  
  64.   
  65.         }  
  66.   
  67.         out.println("  </BODY>");  
  68.   
  69.         out.println("</HTML>");  
  70.   
  71.         out.flush();  
  72.   
  73.         out.close();  
  74.   
  75.     }  
  76.   
  77. }  
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(); } }

由于是通过注入方法获得的EntityManagerFactory对象,所以EntityManagerFactory对象的创建不需要手动创建和关闭,这里与在EJB容器中的获得方法相同。@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) public @interface PersistenceUnit{ String name() default ""; String unitName() default ""; }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值