一、获取:
可以通过标注@PersistenceContext将EntityManager注入到CalculatorBean
@Stateless
public
class
CalculatorBean
implements
Calculator {
@PersistenceContext
//
(unitName="ejb3trail")
protected
EntityManager em;
//
}
Note: 如果应用有多个EntityManager配置, 而每个表示不同的数据库连接, 则unitName用来表示which EntityManager object to inject. 更多信息见稍后Configure Persistence Context一节。
二、保存: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();
}
}
五、自动更新
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();
}
}
与数据库同步:
如果更新发生在上例中的每一次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标注。
@Entity
@EntityListener(TimedRecordEntityListener.
class
)
public
class
TimedRecord
extends
Record {
//
}
TimedRecordEntityListener中的回调方法使用TimedRecord对象作为参数.容器在适当的时机传递这个参数并回调这些方法。
public
class
TimedRecordEntityListener {
@PrePersist
public
prepareTimestamp (TimedRecord rec) {
//
}
@PreUpdate
public
updateTimestamp (TimedRecord rec) {
//
}
}