一、獲取:
可以通過標(biāo)注@PersistenceContext將EntityManager注入到CalculatorBean
@Stateless
public
?
class
?CalculatorBean?
implements
?Calculator?{
??@PersistenceContext?
//
?(unitName="ejb3trail")
??
protected
?EntityManager?em;
??
//
?
?
}
Note: 如果應(yīng)用有多個(gè)EntityManager配置, 而每個(gè)表示不同的數(shù)據(jù)庫(kù)連接, 則unitName用來表示which EntityManager object to inject. 更多信息見稍后Configure Persistence Context一節(jié)。
?
二、保存:EntityManager.persist()
@Stateless
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().
@Stateless
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
?@Stateless
?
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();
???}
?}?
五、自動(dòng)更新?
?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.
?@Stateless
?
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();
???}
?}?
與數(shù)據(jù)庫(kù)同步:?
???? 如果更新發(fā)生在上例中的每一次for循環(huán)中,性能將大打折扣。在默認(rèn)情況下,EntityManager的所有操作都并不是立即進(jìn)行,而是緩存在內(nèi)存中, 它們僅在the current thread (i.e., stack of method calls) 完成時(shí)或在the next database query is issued之前執(zhí)行, 在我們的例子中,EntityManger的更新操作在updateExchangeRate()方法調(diào)用結(jié)束后才立即被執(zhí)行.
出于某些考量,你可以隨時(shí)手動(dòng)調(diào)用EntityManager.flush()對(duì)數(shù)據(jù)進(jìn)行同步更新。
?
使用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.
?
七、實(shí)體BEAN的生命周期
?與 TrailBlazer 第 4, 5 天中的session bean回調(diào)方法非常的類似。
entity bean有如下這些標(biāo)注供EJB容器在適當(dāng)?shù)臅r(shí)候回調(diào)。
@PrePersist
@PostPersist
@PreRemove
@PostRemove
@PreUpdate
@PostUpdate
@PostLoad
同session bean一樣,還有一個(gè)@Remove標(biāo)簽,但不是回調(diào)方法, 作用是: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一樣,可以把這些回調(diào)方法放在一個(gè)單獨(dú)的類中,并在主類中使用@EntityListener標(biāo)注。
@Entity
@EntityListener(TimedRecordEntityListener.
class
)
public
?
class
?TimedRecord?
extends
?Record?{
????
//
?
?
}
TimedRecordEntityListener中的回調(diào)方法使用TimedRecord對(duì)象作為參數(shù).容器在適當(dāng)?shù)臅r(shí)機(jī)傳遞這個(gè)參數(shù)并回調(diào)這些方法。
public
?
class
?TimedRecordEntityListener?{
????@PrePersist
????
public
?prepareTimestamp?(TimedRecord?rec)?{
????????
//
?
?
????}????
????@PreUpdate
????
public
?updateTimestamp?(TimedRecord?rec)?{
????????
//
?
?
????}
}