关于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;
}
0
相关文章