TrailBlazer第11天--EntityManager & Callbacks
Posted on 2006-07-28 02:28 Earth 閱讀(507) 評論(0) 編輯 收藏 所屬分類: JavaEE5/EJB3一、獲取:
可以通過標注@PersistenceContext將EntityManager注入到CalculatorBean
public ? class ?CalculatorBean? implements ?Calculator?{
??@PersistenceContext? // ?(unitName="ejb3trail")
?? protected ?EntityManager?em;
?? // ?


}
Note: 如果應用有多個EntityManager配置, 而每個表示不同的數據庫連接, 則unitName用來表示which EntityManager object to inject. 更多信息見稍后Configure Persistence Context一節。
?
二、保存:EntityManager.persist()
public ? class ?EntityCalculator? implements ?Calculator?{
??@PersistenceContext
?? protected ?EntityManager?em;
?? public ? void ?addFund?(String?name,? double ?growthrate)?{
????Fund?fund? = ? new ?Fund?(name,?growthrate);
????em.persist?(fund);
??}
?? public ? void ?addInvestor?(String?name,? int ?start,? int ?end)?{
????Investor?investor? = ? new ?Investor?(name,?start,?end);
????em.persist?(investor);
??}
?? // ?


}
三、檢索find :
The EntityManager.find() method retrieves an entity bean instance from the database using the entity bean class name (i.e., the database table name) and the entity ID (i.e., the database primary key). In our O/R mapping schema, the entity ID is the Id attribute of the entity bean instance. The following code segment in CalculatorBean shows how to use EntityManager.find().
public ? class ?EntityCalculator? implements ?Calculator?{
??@PersistenceContext
?? protected ?EntityManager?em;
?? // ?


?? public ? double ?calculate?( int ?fundId,? int ?investorId,? double ?saving)?{
????Investor?investor? = ?
????????em.find(Investor. class ,?
????????????????Integer.valueOf(investorId));
????Fund?fund? = ?
????????em.find(Fund. class ,?
????????????????Integer.valueOf(fundId));
???? int ?start? = ?investor.getStartAge();
???? int ?end? = ?investor.getEndAge();
???? double ?growthrate? = ?fund.getGrowthrate();
???? // ?


????TimedRecord?rec? = ?
???????? new ?TimedRecord?(fund,?investor,?saving,?result,?ts);
????em.persist?(rec);
???? return ?result;
??}
}
四、檢索createQuery
? public ? class ?QueryCalculator? implements ?Calculator?{
?
???@PersistenceContext
??? protected ?EntityManager?em;
?
??? public ?Collection? < Fund > ?getFunds?()?{
????? return ?em.createQuery( " from?Fund?f " ).getResultList();
???}
??? public ?Collection? < Investor > ?getInvestors?()?{
????? return ?em.createQuery( " from?Investor?p " ).getResultList();
???}
??? public ?Collection? < TimedRecord > ?getRecords?()?{
????? return ?em.createQuery( " from?TimedRecord?r?order?by?r.id?desc " ).getResultList();
???}
??? public ?Collection? < TimedRecord > ?filterRecords?( double ?low,? double ?high)?{
????? return ?em.createQuery(
????????? " from?TimedRecord?r?where?r.result?>?:low?AND?r.result?<?:high " )
?????????.setParameter?( " low " ,? new ?Double?(low))
?????????.setParameter?( " high " ,? new ?Double?(high))
?????????.getResultList();
???}
?}?
五、自動更新?
?To update rows in a table, you should first retrieve those rows into entity bean objects via the EntityManager API. Then, you can just use the regular setter methods to update any data attributes (mapped to table columns in the database). The updates are automatically sent to the database. The code segment below shows how the update works.
? public ? class ?UpdateCalculator? implements ?Calculator?{
?
???@PersistenceContext
??? protected ?EntityManager?em;
?
??? public ?Collection? < TimedRecord > ?getRecords?()?{
????? return ?em.createQuery( " from?TimedRecord?r?order?by?r.id?desc " ).getResultList();
???}
?
??? public ? void ?updateExchangeRate?( double ?newrate)?{
?????Collection? < TimedRecord > ?rc? = ?em.createQuery( " from?TimedRecord?r " ).getResultList();
????? for ?(Iterator?iter? = ?rc.iterator();?iter.hasNext();)?{
???????TimedRecord?r? = ?(TimedRecord)?iter.next();
???????r.setSaving(r.getSaving()? * ?newrate);
???????r.setResult(r.getResult()? * ?newrate);
?????}
????? // ?em.flush();
???}
?}?
與數據庫同步:?
???? 如果更新發生在上例中的每一次for循環中,性能將大打折扣。在默認情況下,EntityManager的所有操作都并不是立即進行,而是緩存在內存中, 它們僅在the current thread (i.e., stack of method calls) 完成時或在the next database query is issued之前執行, 在我們的例子中,EntityManger的更新操作在updateExchangeRate()方法調用結束后才立即被執行.
出于某些考量,你可以隨時手動調用EntityManager.flush()對數據進行同步更新。
?
使用Merge更新:
The local EntityManager keeps track of the entity beans it retrieved and captures all updates to the beans objects that need to be synchronized to the database. But how about entity bean instances that are not obtained by the local EntityManager? For instance, what if you have a TimedRecord bean that is sent via a serialized network connection? How do you update it and get the changes synchronized to the database? To do that, you can use the EntityManager.merge() method and pass the bean instance as the call parameter.
In general, if you update an entity bean obtained outside of the local thread, you need to invoke the EntityManager.merge() method to merge its values back to the database.
?
七、實體BEAN的生命周期
?與 TrailBlazer 第 4, 5 天中的session bean回調方法非常的類似。
entity bean有如下這些標注供EJB容器在適當的時候回調。
@PrePersist
@PostPersist
@PreRemove
@PostRemove
@PreUpdate
@PostUpdate
@PostLoad
同session bean一樣,還有一個@Remove標簽,但不是回調方法, 作用是:remove the bean instance from the EntityManager managed context. The bean instance becomes detached and you cannot use it again. The changes you made in this bean instance, if not committed, will be lost.
同session bean一樣,可以把這些回調方法放在一個單獨的類中,并在主類中使用@EntityListener標注。
@EntityListener(TimedRecordEntityListener. class )
public ? class ?TimedRecord? extends ?Record?{
???? // ?


}
TimedRecordEntityListener中的回調方法使用TimedRecord對象作為參數.容器在適當的時機傳遞這個參數并回調這些方法。
????@PrePersist
???? public ?prepareTimestamp?(TimedRecord?rec)?{
???????? // ?


????}????
????@PreUpdate
???? public ?updateTimestamp?(TimedRecord?rec)?{
???????? // ?


????}
}