EntityManager:seam新手必读(二)

时间:2022-04-06 16:09:24
    一旦entity数据有所改变,将反映到数据库中。 不能确认EntityManager何时会向数据库写入更新的数据。但是这一事件肯定会发生,一般是马上,但不会晚于 EntityManager消失 ;)。你可以控制触发更新数据库:

EntityManager:seam新手必读(二)em.flush();    
     这将强制 EntityManager 立刻将更新写入数据库。请记住,这条语句将影响所有状态为 MANAGED entitie,而不是当前一个。不过,一般情况下不必这么做。
    如果你想反其道而行之,也就是从数据库载入一个 entity (因为别人可能已经修改其数据),这么写:
EntityManager:seam新手必读(二)em.refresh(entity);    
    怎样删除一个entity呢?很简单:
EntityManager:seam新手必读(二)em.remove(entity);    
    现在, entity的状态成为 REMOVED,表示其已经被列入删除计划。你可以用 flush()语句,让删除动作马上发生,但没必要这么干。

    现在来点复杂的。当注入
EntityManager 的时候,有一个事务范围持久上下文 Transaction Scoped Persistence Context )。当 entitie处在 MANAGED状态时,其处在持久上下文( persistence context )的“容器”中。“事务范围”意味什么?首先,什么是“事务”?

    EJB3
Stateful 和 Stateless beans (依同名标注辨别)的每个方法调用都包装到一个事务内。(顺便说一下,事务一旦发生 RuntimeException,即发生会滚,对数据的改变将撤销 )。因此,持久上下文( persistence context )将在调用方式之前建立,方式调用结束后移除。然后,持久上下文中管理的所有entity的状态成为 DETACHED。

    假设在你的bean里头有两个
method。第一个是 load(), 它调用 find函数取出数据库中的一个实体。第二个是 finish(),返回一个JSF输出。调用这两个函数中间修改了实体数据。这种修改持久到数据库中吗?回答是:NO。

   
load() 函数结束后, EntityManager'的持久上下文结束,它所有管理过的entity状态成为 DETACHED。一个后果是,与新entity相反-有一个ID,但他们的状态并不是 managed ,对这些 detached entities 所作的更新并不影响数据库。如果你想使一个 entity 更新数据库,需要将其重新 attach到持久上下文。在这个例子中,在 finish()方法中增加以下行:
EntityManager:seam新手必读(二)em.merge(entity);    

    现在这个
entity 已经合并到 finish()方法的持久上下文中(记住,每个方法是一个事务,每个事物有自己的持久上下文),并且状态是又变为 managed。

     这样做是可以的,但有两个缺点:
-需要调用merge(->多了一些代码)
-调用find()之前,如果某个entity未初始化,而你又要存取它的某些属性,将会得到
exception 错误。

    有一个简单的解决方案:扩展持久上下文的生命期,这样,当调用多个事务/方法时,entity状态始终保持为
managed 。因此,我们改变 EntityManager的注入方式:
EntityManager:seam新手必读(二)@PersistenceContext(type=PersistenceContextType.EXTENDED
EntityManager:seam新手必读(二)
private EntityManager em;   

     现在,
managed entities "生活在"一个扩展持久上下文中( Extended Persistence Context )。

    你甚至无须呼叫merge()方法,因为eitities从未被
DETACHED。你可能会问:普通事务范围( "normal" (transaction scoped) )持久上下文的好处是什么?它一直依附于你做的事情(小崔:什么意思?) 。扩展上下文需要更多的内存,因为即使你不需要,它也一直存在于内存。并且一旦entities被其他的bean改变(它们有自己的持久上下文),你需要显式地调用 refresh()方法(在 overviews/list页面 )。当你需要普通 EntityManager 时它就在那里,因其生命周期短,只能操作即时数据 ;)
   
    当谈及列表:为取得不止一个实体,而是一个实体集合,使用:
EntityManager:seam新手必读(二)List<Entity> entities = em.createQuery("from Entity").getResultList();    

    这不是“真正” SQL,而是类似sql的东西,称之为 EJBQL。你可以用它执行某些条件查询,排序等,如
EntityManager:seam新手必读(二)..."from Entity where lastName=".nameToSearchFor." order by firstName"    
    仅使用 entity属性名称即可。关于 EJBQL 要说的太多了,但对于本篇介绍来说这已足够。

    好,基本介绍到此为止。希望对你来说,在如何使用
EntityManager方面, 这一个简单易懂的介绍。

    我已声明过,不能保证百分百正确。并且肯定有许多英语语法错误(对不起,我是德国人,不要打我PP噢)。欢迎斧正。


2007.4.11翻译自:
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=88460