`
zzc1684
  • 浏览: 1228657 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

操作EntityManager

阅读更多

操作EntityManager

Interacting with an EntityManager

现 在你已经学会如何部署和获取指向EntityManager的引用了,接下来你将学习如何正确地操作EntityManager。 EntityManager API包含了插入和删除实体的数据库操作方法,将游离的实体实例合并更新到数据库的方法。它还包含了一组丰富的查询API,你可以藉此来创建查询对象。

package javax.persistence;

public interface EntityManager {

   public void persist(Object entity);

   public <T> T find(Class <T> entityClass, Object primaryKey);

   public <T> T getReference(Class <T> entityClass, Object primaryKey);

   public <T> T merge(T entity);

   public void remove(Object entity);

   public void lock(Object entity, LockModeType lockMode);

   public void refresh(Object entity);

   public boolean contains(Object entity);

   public void clear();

   public void joinTransaction();

   public void flush();

   public FlushModeType getFlushMode();

   public void setFlushMode(FlushModeType type);

   public Query createQuery(String queryString);

   public Query createNamedQuery(String name);

   public Query createNativeQuery(String sqlString);

   public Query createNativeQuery(String sqlString, String resultSetMapping);

   public Query createNativeQuery(String sqlString, Class resultClass);

   public Object getDelegate();

   public void close();

   public boolean isOpen();

}

 

持久化实体

Persisting Entities

对 实体进行持久化就是将其插入到数据库中。你所持久化的是还未曾保存到数据库中的实体。要持久化一个实体,首先是为实体的实例分配内存,然后设置成员属性, 并设置好与其他对象可能存在的任何关联关系。换言之,你可以像操作普通Java对象那样初始化一个entity bean。一旦完成这一步,你就可以调用EntityManager.persist()方法来保存该实体了。

Custom cust = new Customer();

cust.setName("Bill");

entityManager.persist(cust);

当 调用persist()方法后,EntityManager会将Customer添加到等待数据库插入的队列中,对象实例即处于托管状态。实际的插入操作 何时发生则取决于多种因素。如果在事务范围内调用了persist()方法,插入操作可能马上执行,也可能在事务提交时执行,这依赖于flush模式(本 章的后续部分会讲到)的取值。任何时候,你都可以通过调用flush()方法在一个事务内强制手工插入。当且仅当entity manager是extended persistence context时,你才可以在事务范围外调用persist()方法。此时,插入操作会被保存到队列中,直到persistence context与某个事务关联之后才被执行。一个由EJB容器注入的extended persistence context会自动与JTA事务关联。而对于通过EntityManagerFactory API手动创建的extended context,你必须调用Entity.Manager.joinTransaction()方法才能使之与事务关联。

如 果实体与其他实体存在任何关联关系,且正确设置了级联策略(cascade policies),关联实体同样可以被保存到数据库中。我们将在第7章讨论级联。在第6章里,我们还将看到当persist()方法被调用时,Java Persistence能够自动生成主键。因此在上例中,如果你启用了自动主键生成功能,在persist()方法执行完毕后,你将会看到生成的主键。

如 果传入 persist()方法的参数不是实体类型的,persist()方法将抛出Illegal- ArgumentException异常。在transaction-scoped persistence context里,事务范围外的persist()调用会引起TransactionRequiredException异常。而在extended persistence context中,事务范围外的persist()调用则是合法的;不过在persistence context与事务关联之前,数据库插入操作是不会被执行的。

查找实体

Finding Entities

EntityManager提供了两种在数据库中查找对象的机制:一种是使用entity manager提供的简单方法根据主键在数据库中查找实体,另一种则是创建查询对象并执行查询。

find()和getReference()方法

EntityManager提供了两个不同的方法允许你通过主键来查找实体。

public interface EntityManager {

   <T> T find(Class<T> entityClass, Object primaryKey);

   <T> T getReference(Class<T> entityClass, Object primaryKey);

}

 

这两个方法都接受实体的 class和代表实体主键的对象作为参数。由于它们使用了Java泛型方法,无需任何显示的类型转换即可获得特定类型的实体对象。那么,我们该如何区别使 用这两个方法呢?在无法从数据库中找到指定实体时,find()方法会返回null。它还会根据延迟加载策略(lazy-loading,详见第6章相关 讨论)初始化entity bean的内部状态。

Customer cust = entityManager.find(Customer.class, 2);

在 本例中,我们查找一个主键 ID值为2的Customer对象。find()方法期望第二个参数的类型为Object,而非上述的基本数据类型,那么它是怎么通过编译的呢?此处,我 们用到了Java 5的一个新特性,称作自动装箱(autoboxing),它将基本数据类型直接转换为相应的对象类型。因此,常量2实际上是被转换成了 java.lang.Integer类型。

Customer cust = null;

try {

   cust = entityManager.getReference(Customer.class, 2);

} catch (EntityNotFoundException notFound) {

   // 恢复逻辑

}

 

getReference() 方法与find()方法的不同之处在于:如果在数据库中找不到相应的实体,
getReference()方法将抛出 javax.persistence.EntityNotFoundException异常;
并且该方法并不保证返回实例的内部状态会被初始化。

如果传入的参数不是实体类型,find()方法和getReference()方法都会抛出
Illegal- ArgumentException异常。你可以在事务范围之外调用这两个方法,
其行为依据persistence context的不同而有所不同:
若EntityManager是transactionscoped persistence context,则会返回游离对象;
而若是extended persistence context,则返回托管对象。

查询

持久对象也可以通过EJB QL来查询。与EJB 2.1不同的是,此处不再有任何finder方法了,
你必须通过调用EntityManager的createQuery()、createNamedQuery()或createNativeQuery()方法
来创建Query对象进行查询。

 

public interface EntityManager {

   Query createQuery(String queryString);

   Query createNamedQuery(String name);

   Query createNativeQuery(String sqlString);

   Query createNativeQuery(String sqlString, Class resultClass);

   Query createNativeQuery(String sqlString, String resultSetMapping);

}

创建并执行EJB QL查询与创建并执行JBDC PreparedStatement非常相似。

Query query = entityManager.createQuery("from Customer c where id=2");

Customer cust = (Customer)query.getSingleResult();

 

我们将在第9章详细介绍查询和EJB QL。

所有由find(),getResource()或查询对象所返回的实体实例都将保持托管状态,直至其所在的persistence context被关闭为止。亦即,期间再次调用find()或者任何其他的方法,都将返回同样的实体对象实例。

更新实体

Updating Entities

一 旦你调用了find(),getReference(),或创建并执行了一次查询,所得的entity bean实例在persistence context关闭前仍将处于托管状态。在此期间,你可以像其他对象那样随便更改entity bean实例的状态,任何更改都将被自动(取决于flush模式)或手工(通过调用flush()方法)地同步到数据库中。

@PersistenceContext EntityManager entityManager;

@TransactionAttribute(REQUIRED)

public void updateBedCount(int id, int newCount) {

   Cabin cabin = entityManager.find(Cabin.class, id);

   cabin.setBedCount(newCount);

}

 

在这段代码中,persistence context一直与某个事务关联,因此find()方法返回的Cabin实例是受EntityManager托管的。亦即,你可以更改对象实例,一旦 EntityManager决定将更改从内存同步到数据库时,数据库便会被自动更新。

合并实体

Merging Entities

在Java Persistence中,你可以使用EntityManager的merge()方法,将游离实体的状态变更合并到数据库中。假设有一个远程Swing 客户端,它调用了TravelAgent session bean的远程方法,用以查找数据库中的cabin实体。

@PersistenceContext EntityManager entityManager;

@TransactionAttribute(REQUIRED)

public Cabin findCabin(int id) {

   return entityManager.find(Cabin.class, id);

}

 在本例中,由于findCabin()方法处于一个独立的JTA事务中,persistence context将在方法结束时被EJB容器关闭。当Cabin实例被序列化时,它会脱离entity manager的管理并被送到远程的Swing客户端。此时,该Cabin实例是一个普通的Java对象,并且不再关联于任何entity manager。你可以像对待普通Java对象那样,调用该对象的getters和setters。Swing客户端更改了这一Cabin实例的状态,然 后将其重新送回服务器。

Cabin cabin = travelAgent.findCabin(1);

cabin.setBedCount(4);

travelAgent.updateCabin(cabin);

TravelAgentBean.updateCabin()方法接受cabin实例作为参数,
并通过merge()方法将它合并到当前EntityManager管理的persistence context中。

@PersistenceContext EntityManager entityManager;

@TransactionAttribute(REQUIRED)

public void updateCabin(Cabin cabin) {

   Cabin copy = entityManager.merge(cabin);

}

 

由远程Swing客户端所作的修改将在EntityManager决定与数据库进行同步时被写回到数据库中。updateCabin()方法在合并cabin时遵循下列规则。

若 EntityManager未曾管理过与传入的cabin参数有着相同ID的Cabin实例,则 merge()方法会创建该参数的一份完整拷贝并将其作为方法的返回值。该份拷贝受entity manager管理,并且任何针对该份拷贝的setter方法调用所引起的状态更改,在EntityManager决定执行flush操作时,都会被同步 到数据库中。而传入的cabin参数仍将保持游离状态,不受托管。

若与传入的cabin参数有着相同主键的Cabin实例早已处于EntityManager的管理之中,则cabin参数的内容将被复制到托管的对象实例中。merge()方法将返回该托管

实例。而传入的cabin参数将仍然保持游离状态,不受托管。

同 样,如果传入merge()方法的参数不是实体类型,merge()方法将会抛出Illegal- ArgumentException异常;如果该方法在transaction-scoped persistence context范围外调用,则会引起TransactionRequiredException异常;而在extended persistence context中,事务范围外的merge()调用是允许的。但是,在persistence context重新与事务关联之前,更新操作都不会被同步到数据库中。

删除实体

Removing Entities

调 用EntityManager.remove()可以将实体从数据库中删除。不过,remove()方法并不立即生效,而是在EntityManager 决定执行flush操作时,根据定义好的flush规则(将在本章的后续部分讨论),才会执行SQL DELETE操作。

@PersistenceContext EntityManager entityManager;

@TransactionAttribute(REQUIRED)

public void removeCabin(int id) {

   Cabin cabin = entityManager.find(Cabin.class, id);

   entityManager.remove(cabin);

}

 

调用remove()方法之 后,cabin实例将不再受entity manager托管而成为游离对象如果其他实体对象与该对象存在关联关系,则这些对象也将依据级联规则(将在第7章中讨论)被相应删除。只有通过调用 persist()方法重建实体实例,remove()操作才可以被撤销(undone)。

传 入remove()方法的参数若不是实体类型,remove()方法将抛出IllegalArgument- Exception异常;如果该方法在transaction-scoped persistence context范围外调用,则会引起TransactionRequiredException异常;而在extended persistence context中,事务范围外的remove()调用是允许的。但是,在persistence context重新与事务关联之前,数据是不会从数据库中删除的。

refresh()

refresh()

如果发现当前受托管的实体并非数据库中的最新数据,你可以调用EntityManager. refresh()方法。refresh()方法会根据数据库的情况刷新内存中实体的状态,同时覆盖对实体所做的任何修改。

@PersistenceContext EntityManager entityManager;

@TransactionAttribute(REQUIRED)

public void refreshCabin(int id) {

   Cabin cabin = entityManager.find(Cabin.class, id);

   entityManager.refresh(cabin);

}

 

如果entity bean有关联实体,那么根据在实体映射元数据中设置的级联策略,那些关联实体也会被相应刷新。

传 入refresh()方法的参数若不是实体类型,refresh()方法将抛出IllegalArgument- Exception异常;在transaction-scoped persistence context范围外的refresh()调用则会引起TransactionRequiredException异常;而在extended persistence context中,事务范围外的remove()调用是允许的。如果需要刷新的实体对象在数据库中不存在(例如被其他线程或进程删除了),则会抛出 EntityNotFoundException异常。

contains()方法与clear()方法

contains() and clear()

contains()方法接受实体实例作为参数,如果该对象实例目前正受persistence context管理,则返回true。若该参数并非实体类型,则会抛出IllegalArgumentException异常。

你 可以使用EntityManager.clear()方法将persistence context中所有的托管实体都变成游离对象。需要注意的是,一旦你调用了clear()方法,对实体所做的任何修改都将被丢弃。因此,使用 clear()时需要格外小心。在调用clear()之前,先调用flush()方法以免丢失更改实为明智之举。

flush()方法和FlushModeType

flush() and FlushModeType

正 如上文所述,调用persist(),merge(),remove()方法之后,这些更改操作只有在 EntityManager决定执行flush操作时才会被同步到数据库中。你也可以在任何时候通过调用flush()方法做强行同步。缺省情况 下,flush操作会在相关查询执行之前和事务提交之时自动执行(一些低效的Java Persistence实现甚至可能会在任何查询执行之前都做flush操作)。但需注意的是,与一般查询不同,调用find()和 getReference()方法并不会引起flush。这是因为通过主键来查询实体是不会受任何更新操作的影响的。

可以通过枚举类型javax.persistence.FlushModeType来控制和修改这一默认行为。

public enum FlushModeType {

   AUTO,

   COMMIT

}

AUTO是前述的默认行为。COMMIT则表示,仅当事务提交时才对更改做flush操作,而

在任何查询执行之前都不会引发flush操作。你可以通过调用setFlushMode()方法来指定EntityManager的FlushModeType。

可 是我们为什么需要手工指定FlushModeType呢?默认的 flush行为听起来很有道理:如果你正在查询数据库,一定想要确保在事务中所做的任何更新都被flush到数据库。这样,查询结果才会反映这些更新。否 则,更新就可能不会体现在查询结果中;而在事务提交时,很显然,你希望对更改做flush操作。

尽 管如此,出于性能的考虑,FlushModeType.COMMIT 也是有用武之地的。数据库应用调优的最好办法就是减少不必要的数据库访问。一些Java Persistence实现可以在一次batch JDBC调用中执行所有必要的更新操作。而如果updateBeds()方法使用缺省的Flush- ModeType.AUTO模式,那么执行每次查询时都会执行相应的SQL UPDATE。而使用COMMIT,则允许entity manager在一次批处理调用中执行所有的更新操作。这会大大减少数据库访问的次数。此外,UPDATE通常会使记录处于写锁定状态(write- locked)。使用COMMIT模式时,对数据库的锁定只在JTA事务提交期间发生,从而减少了事务对数据库占用的总体时间。

锁定

Locking

EntityManager API同时支持读锁和写锁,由于锁定行为与事务的概念紧密关联,我们将在第16章详细讨论lock()方法的使用。

getDelegate()

getDelegate()

getDelegate() 方法允许你获得一个指向底层 persistence provider对象的引用,该persistence provider实现了EntityManager接口。大多数厂商都提供了针对EntityManager接口的API扩展,为了使用这些扩展功能,你 可以将获取到的delegate对象强制类型转换为厂商的私有接口。虽然从理论上讲,你应该可以编写出厂商无关的代码。但实际上,多数厂商都提供了大量针 对Java Persistence的扩展,你可以在应用程序中充分利用这些功能。而getDelegate()方法提供了一种获取并使用厂商专有API的途径。

分享到:
评论

相关推荐

    EntityManager

    在EJB(Enterprise JavaBeans)环境中,Session bean 或 MDB(Message-Driven Bean)与Entity bean交互时,EntityManager是主要的接口,它负责处理Entity bean的所有查询、插入、更新和删除操作。EntityManager实例...

    entitymanager(hibernate)

    而实体管理器(EntityManager)是Java Persistence API(JPA)的一部分,它提供了与Hibernate集成的关键接口,用于管理和操作数据。当我们谈论"entitymanager(hibernate)"时,意味着我们要探讨如何在Java项目中将这...

    Hibernate EntityManager Document

    本文档为Hibernate 3.3.0.GA版本的EntityManager使用指南,主要介绍了如何在不同的环境中使用EntityManager管理持久化对象,包括实体的状态管理、查询操作、事务处理等内容。 #### 一、架构 ##### 1.1 定义 - **...

    EntityManager Demo

    【描述】:EntityManager是Java Persistence API (JPA)中的核心组件,主要用于管理实体(Entity)对象及其在数据库中的持久化操作。这个Demo将展示如何使用EntityManager进行基本的数据操作,包括创建、查询、更新和...

    Hibernate EntityManager用法

    Hibernate EntityManager在Hibernate Session之上提供了一层抽象,使得开发者可以使用JPA标准的API来操作数据,同时也保留了Hibernate的一些高级特性。 **2. 配置Hibernate EntityManager** 在使用Hibernate ...

    OpenJpaExample

    4. 在事务中操作EntityManager,如保存实体、查询实体、更新实体和删除实体。 5. 使用JPQL进行复杂查询。 6. 提交或回滚事务,完成数据库操作。 **总结** OpenJPAExample项目是一个基础的OpenJPA学习示例,它展示...

    jpa需要的jar包

    - **获取和操作EntityManager**: 通过EntityManager进行CRUD操作。 - **执行查询**: 使用JPQL或Criteria API编写查询,获取数据。 6. **JPA的优势** - **简化代码**: ORM减少了手动编写SQL的需求,使得代码更...

    EntityManager API方法详解

    Session bean or MD bean对Entity bean的操作(包括所有的query, insert, update, delete操作)

    hibernate-entitymanager-3.2.jar.zip

    Hibernate EntityManager 是 Hibernate 项目的一部分,它是一个符合 JPA(Java Persistence API)规范的 ORM 解决方案,为开发者提供了一种更加面向对象的方式来处理数据库操作。在 Hibernate EntityManager 3.2 ...

    hibernate-entitymanager-3.4.0.GA

    【标题】"hibernate-entitymanager-3.4.0.GA" 是一个与Java持久化框架Hibernate Entity Manager相关的库,这个版本号表明它是2009年左右发布的一个稳定版本。Hibernate Entity Manager是JPA(Java Persistence API)...

    hibernate-entitymanager-4.3.4.Final.zip

    【标题】"hibernate-entitymanager-4.3.4.Final.zip" 是一个与Hibernate实体管理器相关的压缩包,其中包含的是Hibernate ORM框架的一个特定版本——4.3.4.Final。Hibernate实体管理器是Java开发中用于实现Java持久化...

    Hibernate core+annotations+entitymanager 指南小集合

    最后,通过EntityManager进行数据操作,享受JPA带来的标准化接口和强大的ORM功能。 综上所述,理解并熟练运用Hibernate的这三个关键组件对于任何Java开发人员来说都是至关重要的。掌握它们不仅能够提高开发效率,还...

    Spring EntityManager 不能扫描jar 中的class文件

    在Spring框架中,EntityManager是Java Persistence API (JPA) 的核心接口,用于处理数据库操作。然而,有时在尝试使用Spring管理持久层时,可能会遇到一个问题:“Spring EntityManager 不能扫描jar中的class文件”...

    EntityManager,实体类数据库访问管理层

    有了实体类CUstoms,下面就可以操作实体类跟操作数据库一样的啦,我们新建一个实体类管理类 CustomsManager.cs public class CustomsManager:EntityManager { public Customs GetByName(string name) { //创建...

    hibernate-entitymanager-3.3.0.GA

    - **操作实体**:使用EntityManager进行增删改查操作,如persist()、merge()、remove()和find()。 - **事务处理**:在开始和结束操作之间启动和提交事务。 - **查询数据**:使用JPQL或Criteria API执行查询,并...

    hibernate-entitymanager-3.3.2.GA

    6. **操作实体**: 实例化实体,调用EntityManager的persist()、merge()、remove()、find()等方法完成CRUD操作。 7. **查询执行**: 使用createQuery()、createCriteria()创建查询,通过JPQL或Criteria API获取结果集...

    hibernate-entitymanager-3.2.0.GA.zip

    - 实体管理器:使用EntityManager实例来操作实体,如创建(persist)、加载(find)、更新(merge)、删除(remove)等。 - JPQL查询:编写JPQL语句,执行查询并获取结果集。 - 事务处理:通过EntityManager的...

    hibernate-entitymanager-3.2.1.GA.zip

    EntityManager是与数据存储进行交互的主要接口,负责对象的创建、读取、更新和删除(CRUD)操作。通过它可以管理实体的状态,执行查询,以及进行事务控制。 4. **实体(Entity)** 实体是应用程序中与数据库表...

Global site tag (gtag.js) - Google Analytics