Let's go inside

this blog is deprecated as a result of laziness.
posts - 59, comments - 2, trackbacks - 0, articles - 0

TrailBlazer第11天--EntityManager & Callbacks

Posted on 2006-07-28 02:28 Earth 阅读(501) 评论(0)  编辑  收藏 所属分类: JavaEE5/EJB3

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

只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问