技术开发 频道

关于EJB的持久化对象技术分析


EJB客户端
 
  在本例中,你可以在同一JVM虚拟机中访问EJB。这种设计简化了我们的一些工作,要获得EJB的home接口,我们需要进行一个特殊的下溯造型。列表4简述了UserService对象,它用来访问我们的EJB。
 
UserService对象
 
public class UserService
{
 private static LocalUserHome home = null;
 private static LocalUserHome getUserHome()
 throws NamingException
 {
  if (home != null)
  {
   return home;
  }
// 取得一个上下文
InitialContext ctx = new InitialContext();
// 取得对UserEJB的一个引用
System.out.println("Looking up EJB...");
Object objRef = ctx.lookup("local/UserEJB");
// 取得UserEJB的home接口
home = (LocalUserHome)objRef;
return home;
 }
 public static UserInfo getUser(String userID)
 {
  UserInfo userInfo = null;
  try
  {
   LocalUserHome home = getUserHome();
   LocalUser localUser = null;
   try
   {
    System.out.println("Finding user...");
    localUser = home.findByPrimaryKey(userID);
   }
   catch (FinderException e)
   {
 }
 if (localUser == null)
 {
  System.out.println("Creating user...");
  localUser = home.create(userID,"John " + userID + " Doe","123 anywhere st.","Seattle","WA","87654");
 }
 System.out.println("EJB returned User ID: " + localUser.getUserID());
 userInfo = convertToUserInfo(localUser);
 System.out.println("User FullName: " + localUser.getFullName());
}
catch (Exception e)
{
 System.err.println(e.toString());
}
return userInfo;
}
 
private static UserInfo convertToUserInfo(LocalUser localUser)
{
 
UserInfo userInfo;
userInfo = new UserInfo();
userInfo.setId(localUser.getUserID());
userInfo.setFullName(localUser.getFullName());
userInfo.setAddress(localUser.getAddress());
userInfo.setCity(localUser.getCity());
userInfo.setState(localUser.getState());
userInfo.setZip(localUser.getZip());
return userInfo;
 }
}
 
  请注意,UserService对象首先试着通过findByPrimaryKey()方法来找到一个EJB的实例,并在这个方法中传递一个用户ID的参数。如果没有找到实体EJB的实例,UserService对象将调用EJB的home接口中的create()方法来创建一个新的EJB实例。
 
  findByPrimaryKey()方法在调用过程中首先被EJB容器拦截,EJB容器试着从数据库中找出一个与用户ID相同主键的记录。create()方法将在数据库中插入一个主键等于用户ID的记录。
 
EJB查询语言(EJB QL)
 
  EJB规范提供了一种名为EJB QL的对象查询语言,用来查询CMP。这种对象查询语言实际上被容器转化为SQL语言。EJB QL语言用来实现EJB的home接口中的find()查询方法,并执行实体EJB定义的一些内部的select方法。这些EJB QL一般放在应用程序的部署描述文件中。
 
  以下XML代码(选自于jaws.xml文件)定义了在UserEJB的home接口中findByState()方法与相应EJB QL之间的映射。这个示例程序用这个EJB QL查询语言及相应的find()方法寻找给出状态的某个用户。
 
<entity>
...
<query>
<query-method>
<method-name>findByState</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
[!CDATA[
SELECT DISTINCT object(u)
FROM UserEJB u
WHERE u.STATE = ?1]]
</ejb-ql>
</query>
</entity>
 
  在以上的定义当中,ejb-ql标签定义了实际使用的EJB QL。当你只想查找一个特定类型的对象时,必须要在查询语言中加入object关键字。另外这个查询中的"?1"的作用类似于JDBC中的PrepareStatement,表明这个查询是一个参数化查询。如果有多个参数,则依次为"?2"、"?3"以此类推,这些参数与查询方法findByState()中的参数表从"?1"开始一一对应。
 
  在上例中,"?1"将被findByState()方法的第一个名为state的参数所取代。除此之外,CMP还有一个名为findAll()或findByPrimaryKey()的
内置方法,你只需要定义它们,而不需实现任何代码,EJB容器会为你自动生成关于这两个方法的代码。
 
  在下面,UserService类定义了一个名为getUsersByState()的方法。这个方法调用UserEJB的home接口上的findByState()方法,EJB容器会拦截这个方法,然后执行定义在jaws.xml文件中的EJB QL查询语言。
 
通过用户状态来查找用户信息
 
public static UserInfo[] getUsersByState(String state)
{
 UserInfo[] users = null;
 // 找出所有收入高于John的职员
 try
 {
  LocalUserHome home = getUserHome();
  Collection userList = home.findByState(state);
  System.out.println("Found userList");
  if (userList != null)
  {
   users = new UserInfo[userList.size()];
   int i = 0;
   Iterator iter = userList.iterator();
   while (iter.hasNext())
   {
    LocalUser localUser = (LocalUser)iter.next();
    users[i++] = convertToUserInfo(localUser);
   }
  }
 }
 catch (NamingException e)
 {
  System.err.println(e.toString());
 }
 catch (FinderException e)
 {
  System.err.println(e.toString());
 }
 return users;
}
 
  由于Java树型对象与表格型的关系数据库中在构架上的差异,对于开发者来说,将Java对象持久化到关系型数据库中这一工作是一件非常复杂的事情。它们之间的这种差异引发了若干种对象持久技术的产生,以使得关系型世界与对象世界之间的鸿沟日益缩小。EJB框架提供了一个基于容器管理的持久化机制,如果使用得当,将会是一种提供给开发者的优秀解决方案。
0
相关文章