seam 中的EntityManager

关于EntityManager有何用处?它管理你的entities ;)。 那是一些简单的java对象,通过getters and setters具备一些属性。这些属性之一是id(一般是Long数据类型),并且这些class必须以@Entity注解(annotated )。在seam的源码中可以找到一大批这样的例子,例如booking例子。在seam中,一件很重要的事情就是,每个Entity都有一个 @Name 注解(annotation),这样,它们才能被注入到其他seam部件(component)中。
    假设我们有这样一个entity class,叫做"Entity"。其生命周期内包含以下功能:

增Create

查Research

删Delete

改Update

EntityManager 提供了这些功能。首先,如何把EntityManager 引入我的代码?很简单:

@PersistenceContext
private EntityManager em;    

    好了,我们看看一个Entity 进程如何产生:

Entity entity =  new Entity();    

    这很简单。现在,这entity 的状态是NEW/TRANSIENT 。这意味着一个entity已经存在于你的应用程序中,但并不具有id,也不存在于你的数据库中。

    由于我们要使它持久化(即它应被写入数据库),我们应把它的状态转换为MANAGED 。

em.persist(entity);    

    现在,此entity由EntityManager管理了。EntityManager控制entity写入数据库。这动作无须立刻发生,可能把你的entity放在cache,稍后写入数据库。你可以放心,写动作肯定会发生。

Ok, what about reading an existing entity from the database? Therefore we use:

好,如何从数据库中读出已存在的entity呢?这样:

Entity entity = em.find(Entity. class, Id);    

    每个entity 有一个id(我已经说过,多数情况下是Long数据类型),通过id你可存取entity。这是这里的第二个参数。第一个参数代表你要存取的Entity class的进程。find操作之后,entity的状态也是MANAGED 。



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

em.flush();    

     这将强制 EntityManager 立刻将更新写入数据库。请记住,这条语句将影响所有状态为 MANAGED entitie,而不是当前一个。不过,一般情况下不必这么做。
    如果你想反其道而行之,也就是从数据库载入一个 entity (因为别人可能已经修改其数据),这么写:
em.refresh(entity);    

    怎样删除一个entity呢?很简单:
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()方法中增加以下行:
em.merge(entity);    

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

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

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

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

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

    这不是“真正” SQL,而是类似sql的东西,称之为 EJBQL。你可以用它执行某些条件查询,排序等,如
..."from Entity where lastName=".nameToSearchFor." order by firstName"    

    仅使用 entity属性名称即可。关于 EJBQL 要说的太多了,但对于本篇介绍来说这已足够。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值