一、获取:
可以通过标注@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) {
//
}
}