EJB3 持久化实体管理器EntityManager

来源:互联网 发布:java生成短信验证码 编辑:程序博客网 时间:2024/06/09 23:39
 

EJB3持久化实体管理器EntityManager

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

@PersistenceContext(unitName="zhaosoft")

EntityManager em;

下面介绍EntityManager 常用的API

1 Entity 获取find()getReference()

如果知道Entity 的唯一标示符,我们可以用find()getReference()方法来获得Entity

@PersistenceContext

protected EntityManager em;

Person person = em.find(Person.class,1);

/*

try {

Person person = em.getReference (Person.class, 1);

} catch (EntityNotFoundException notFound) {

// 找不到记录...

}

*/

当在数据库中没有找到记录时,getReference()find()是有区别的,find()方法会返回null,而getReference()方法

会抛出javax.persistence.EntityNotFoundException 例外,另外getReference()方法不保证实体Bean 已被初始化。如果传递进getReference()find()方法的参数不是实体Bean,都会引发IllegalArgumentException 例外。

6.6.2 添加persist()

保存Entity 到数据库。

@PersistenceContext

protected EntityManager em;

Person person = new Person();

person.setName(name);

//把数据保存进数据库中

em.persist(person);

如果传递进persist()方法的参数不是实体Bean,会引发IllegalArgumentException 例外。

3 更新实体

当实体正在被容器管理时,你可以调用实体的set 方法对数据进行修改,在容器决定flush 时,更新的数据才会同

步到数据库。如果你希望修改后的数据实时同步到数据库,你可以执行EntityManager.flush()方法。

@PersistenceContext

protected EntityManager em;

public void updatePerson() {

try {

Person person = em.find(Person.class, 1);

person.setName("lihuoming"); //方法执行完后即可更新数据

} catch (Exception e) {

e.printStackTrace();

}

}

6.6.4 合并Merge()

merge ()方法是在实体Bean 已经脱离了EntityManager 的管理时使用,当容器决定flush 时,数据将会同步到数据

库中。

@PersistenceContext

protected EntityManager em;

public Person getPersonByID(int personid) {

return em.find(Person.class, personid);

}

public boolean updatePerson(Person person) {

try {

em.merge(person);

} catch (Exception e) {

e.printStackTrace();

return false;

}

return true;

}

下面的代码把实体Bean 返回到了客户端,这时的实体Bean 已经脱离了容器的管理,在客户端对实体Bean 进行

修改,最后把他返回给EJB 容器进行更新操作。客户端调用代码如下:

PersonDAO persondao = (PersonDAO) ctx.lookup("PersonDAOBean/remote");

Person person = persondao.getPersonByID(1); //personid 1 person,此时的person 已经脱离容器的管理

person.setName("张小艳");

persondao.updatePerson(person);

执行em.merge(person)方法时,容器的工作规则:

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

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

如果传递进merge ()方法的参数不是实体Bean,会引发一个IllegalArgumentException 例外。

5 删除Remove()

Entity 从到数据库中删除。

@PersistenceContext

protected EntityManager em;

Person person = em.find(Person.class, 2);

//如果级联关系cascade=CascadeType.ALL,在删除person 时候,也会把级联对象删除。把cascade

属性设为cascade=CascadeType.REMOVE 有同样的效果。

em.remove (person);

如果传递进remove ()方法的参数不是实体Bean,会引发一个IllegalArgumentException 例外。

6 执行JPQL 操作createQuery()

除了使用find()getReference()方法来获得Entity Bean 之外,你还可以通过JPQL 得到实体Bean。要执行JPQL

语句,你必须通过EntityManager createQuery()createNamedQuery()方法创建一个Query 对象。

@PersistenceContext

protected EntityManager em;

Query query = em.createQuery("select p from Person p where p. name=’黎明’");

List result = query.getResultList();

Iterator iterator = result.iterator();

while( iterator.hasNext() ){

//处理Person

}

// 执行更新语句

Query query = em.createQuery("update Person as p set p.name =?1 where p. personid=?2");

query.setParameter(1, “黎明”);

query.setParameter(2, new Integer(1) );

int result = query.executeUpdate(); //影响的记录数

// 执行更新语句

Query query = em.createQuery("delete from Person");

int result = query.executeUpdate(); //影响的记录数

7 执行SQL 操作createNativeQuery()

注意这里操作的是SQL 语句,并非JPQL,千万别搞晕了。

@PersistenceContext

protected EntityManager em;

//我们可以让EJB3 Persistence 运行环境将列值直接填充入一个Entity 的实例,并将实例作为结果返回.

Query query = em.createNativeQuery("select * from person", Person.class);

List result = query.getResultList();

if (result!=null){

Iterator iterator = result.iterator();

while( iterator.hasNext() ){

Person person= (Person)iterator.next();

}

}

// 直接通过SQL 执行更新语句

Query query = em.createNativeQuery("update person set age=age+2");

query.executeUpdate();

8 刷新实体refresh()

如果你怀疑当前被管理的实体已经不是数据库中最新的数据,你可以通过refresh()方法刷新实体,容器会把数据库中的新值重写进实体。这种情况一般发生在你获取了实体之后,有人更新了数据库中的记录,这时你需要得到最新的数据。当然你再次调用find()getReference()方法也可以得到最新数据,但这种做法并不优雅。

@PersistenceContext

protected EntityManager em;

Person person = em.find(Person.class, 2);

//如果此时person 对应的记录在数据库中已经发生了改变,可以通过refresh()方法得到最新数据。

em.refresh (person);

如果传递进refresh ()方法的参数不是实体Bean,会引发一个IllegalArgumentException 例外。

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

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

如果传递的参数不是实体Bean,将会引发一个IllegalArgumentException 例外。

@PersistenceContext

protected EntityManager em;

Person person = em.find(Person.class, 2);

if (em.contains(person)){

//正在被持久化内容管理

}else{

//已经不受持久化内容管理

}

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

在处理大量实体的时候,如果你不把已经处理过的实体从EntityManager 中分离出来,将会消耗你大量的内存。

调用EntityManager clear()方法后,所有正在被管理的实体将会从持久化内容中分离出来。

有一点需要说明下,在事务没有提交前(事务默认在调用堆栈的最后提交,如:方法的返回),如果调用clear()

方法,之前对实体所作的任何改变将会掉失,所以建议你在调用clear()方法之前先调用flush()方法保存更改。

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

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

@PersistenceContext

protected EntityManager em;

public void updatePerson(Person person) {

try {

Person person = em.find(Person.class, 2);

person.setName("lihuoming");

em.merge(person);

//后面还有众多修改操作

} catch (Exception e) {

e.printStackTrace();

}

//更新将会在这个方法的末尾被提交和刷新到数据库中

}

为了只在当事务提交时才将改变更新到数据库中,容器将所有数据库操作集中到一个批处理中,这样就减少了代价昂贵的与数据库的交互。

当你调用persist( ), merge( )remove( )这些方法时,更新并不会立刻同步到数据库中,直到容器决定刷新到数据库中时才会执行,默认情况下,容器决定刷新是在“相关查询”执行前或事务提交时发生,当然“相关查询”除find()getreference()之外,这两个方法是不会引起容器触发刷新动作的,默认的刷新模式是可以改变的。如果你需要在事务提交之前将更新刷新到数据库中,你可以直接地调用EntityManager.flush()方法。这种情况下,你可以手工地来刷新数据库以获得对数据库操作的最大控制。

@PersistenceContext

protected EntityManager em;

public void updatePerson(Person person) {

try {

Person person = em.find(Person.class, 2);

person.setName("lihuoming");

em.merge(person);

em.flush();//手动将更新立刻刷新进数据库

//后面还有众多修改操作

} catch (Exception e) {

e.printStackTrace();

}

}

12 改变实体管理器的Flush 模式setFlushMode()

我们对Flush 模式进行修改需要使用到javax.persistence.FlushModeType,他的定义如下:

public enum FlushModeType {

AUTO,

COMMIT

}

默认情况下,实体管理器的Flush 模式为AUTO,你可以改变他的值,如下:

entityManager.setFlushMode(FlushModeType.COMMIT);

下面说说这两者的区别及使用场合:

FlushModeType.AUTO: 刷新在查询语句执行前(除了find()getreference()查询)或事务提交时才发生,使用场合:

在大量更新数据的过程中没有任何查询语句(除了find()getreference()查询)的执行。

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

find()getreference()查询)的执行。

其实上面两种模式最终反映的结果是:JDBC 驱动跟数据库交互的次数。JDBC 性能最大的增进是减少JDBC 驱动

与数据库之间的网络通讯。FlushModeType.COMMIT 模式使更新只在一次的网络交互中完成,而

FlushModeType.AUTO 模式可能需要多次交互(触发了多少次Flush 就产生了多少次网络交互)。

Jboss EJB3.0 实例教程传智播客(www.itcast.cn)软件培训参考教材

版权所有:黎活明

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

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

@PersistenceContext

protected EntityManager em;

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

获得对Hibernate的引用后,可以直接面对Hibernate 进行编码,不过这种方法并不可取,强烈建议不要使用。

 

  我喜欢的
浏览器
  我喜欢的
文化礼品
  我喜欢的
ISP网站
  我喜欢的
网站
FireFox 2.0
100部奥斯卡影片
时代互联
博告网
   
   
  时代互联10元换空间
  加入博告网日进斗金不是梦!
聚合到我的好诶网博告网 提供的广告

原创粉丝点击