JBuilder9+Weblogic7实战篇ENTITY BEAN的运用

五、使用EJB QL开发查询

5.1 什么是EJB QL

    在关系数据库的操作中查询是经常使用的,主要是通过select语句完成的。Entity Bean作为代表数据库中数据的持久性组件也同样需要查询操作,即能够找到符合某一查询条件的Entity Bean的实例。Entity Bean的查询操作是通过定义finder()方法完成的。对于CMP,定义finder()方法仅仅是声明一个方法,指明finder()方法的参数,该参数通常与查询条件中的参数对应,真正完成查询的动作是由EJB容器完成的。EJB容器要读取部署描述文件ejb-jar.xml(在*.jar/META-INF里)中的<query>项,该项包含了与finder()方法相对应的查询语句。<query>项中的查询语句遵循的语法规范是EJB QL。

    EJB QL的开发查询步骤如下:

1>     Home接口中增加finder()方法,其参数为查询条件中用到的参数;

2>     ejb-jar.xml文件的<query>项定义EJB QL语句。

    EJB QL是EJB2.0新加入的特性,它实现了如何在Home接口中定义各种查找方法。它以SQL-92为基础,可以由容器自动编译,这使得Entity Bean具有更高的可移植性,并且容易部署。

    EJB QL语句由select、where、orderby三个子句组成,其后两个子句是可选的。

    EJB QL查询语句举例如下:

    例1:

    SELECT stu FROM Student AS stu WHERE stu.grade > 5

    该查询语句的含义是查询grade>5的Student Bean实例。“Student”是抽象模式名(Abstract schema name),在ejb-jar.xml文件中<abstract schema name>项指定的名称。“stu”是Student的别名,引入别名的好处是可以引用所代表对象的字段。stu.grade表示Student的grade字段,称为路径表达式。

    例2:

    SELECT i FROM Student As i WHERE i.name = ?1

    该查询语句的含义是查找名字与finder()方法中的第一个参数相同的Student Bean实例。

    WHERE字句的使用说明:

      ?n代表相应的finder()方法的输入参数;

      字符串类型的值要用单引号括起来(如果值中有单引号,则用双引号代替)

WHERE语句中可以使用的表达式和运算符如下:

      +,-,*,/,=,<,<=,>=,>,<>,NOT,AND,OR

      between

      like

      in

      member of

      is null(is not null)

内置函数:

      CONCAT(String first,String second)

      SUBSTRING(String source,int start,int length)

      LOCATE(String source,String patter)

      LENGTH(String source)

 

5.2 查询方法开发实例

5.2.1 打开《Entity Bean的运用(一)》中建立的comSample工程。双击工程窗口中cmpSample.jpx/Cmp,在文档窗口的EJB Designer中用鼠标右键单击Student项,选择Add/Finder菜单项,创建一个finder()方法。

5.2.2 设置finder()方法的各种参数。

    Finder Name: findByName (finder()方法的名字)

      Return type: StudentRemote(返回对象的类型)

      Input parameter: java.lang.String name (输入参数)

      Query: SELECT i FROM Student As i WHERE i.stuname = ?1(完成该查询的EJB QL语句)

5.2.3 查看Student Entity Bean的Home接口(StudentHome.java)会发现增加了一个finder()方法,该方法的定义如下:

    public Student findByName(String name) throws FinderException;

5.2.4右键单击工程窗口中cmpSample.jpx/Cmp,选择Rebuild命令重新打包。

5.2.5 启动Weblogic Server,然后右键单击工程窗口中cmpSample.jpx/Cmp,选择Deploy Options for "Cmp.jar"/Redeploy命令重新部署。

5.2.6 通过EJB Test Client Wizard新建一个客户端程序StudentTestClient2.java,因为EJB已经改变了,所以不能用先前创建的客户端程序。修改main()方法如下:

    public static void main(String[] args)

    {

        StudentTestClient2 client = new StudentTestClient2();

        client.studentRemote = client.findByName("student2");

        System.out.println("The student2's id is " + client.getStuid());

    }

    该方法中通过findByName()方法查找名字为student2的Entity Bean实例,然后输出该Entity Bean对应的stuid值。

 

5.2.7 运行客户端程序,验证结果。

    为了简单,仅使用了一个参数,并且返回的是一个Bean实例。如果查询的结果不唯一,那么需要设置返回值为一个集合(Collection)。

六、建立Entity Bean的关系

6.1 Entity Bean的关系描述

    因为数据之间存在一定的关系,所以代表持久性数据的Entity Bean也应该有相应的关系。例如《Entity Bean运用(一)》中2.1节中创建的两个数据表student和locker,这两个代表学生和课桌的数据表是有关系的,二者通过lockerid相关联。那么作为代表这两个表的Entity Bean,student和locker也应该体现这种关系。Entity Bean的关系是通过在有关系的Entity Bean中建立关系字段完成的。

    EJB2.0支持单向、双向关系,并且Entity Bean之间可以存在一对一(1:1),一对多(1:N)或多对多(N:N)的关系。

6.2 Entity Bean关系开发实例

6.2.1打开《Entity Bean的运用(一)》中建立的comSample工程。参考2.2.9建立一个与locker数据表对应的Entity Bean。

6.2.2 在文档窗口的EJB Designer中单击Locker项,将Interface设置为local/remote,其他项采用默认值。

6.2.3 在文档窗口的EJB Designer中右键单击Locker项,选择Add/Relationship菜单项,将方向箭头指向要建立关系的Entity Bean Student。

6.2.4 将方向箭头指向Student后,可以看到在Locker中增加了一个字段student,该字段是代表与Locker相应的Student,称为关系字段。单击关系字段,可以设置此关系的属性。各项含义如下:

    Relationship name: 关系的名字。

Multiplicity: 选择是一对一、一对多还是多对多的关系。

Navigability: 方向性。选择是单向还是双向的关系。如果选择unidirectional,表示选择单向关系,那么只在Locker中建立代表Student的关系字段。如果选择bidirectional,表示建立双向的关系,那么还将在Student中建立代表Locker的关系字段。

Cascade delete: 设置是否级联删除。级联删除指的是删除一个Entity Bean时,是否相应删除有关系的Entity Bean。此项设置为true还是false取决于具体应用的实际情况。例如在代表班级的Entity Bean与代表班级同学的Student之间建立了关系,由于班级不存在了,其成员student就也没有存在的必要了,所以此项应设置为true。对于本例而言,此处设置为false。

db-cascade-delete:Cascade delete的含义类似,只不过这里设置的是Entity Bean所代表的数据记录的级联删除。

    本例中设置Multiplicityone to one1:1),Navigabilityunidirectional。其他项采用默认值。

 

6.2.5 单击“Relationship properties”界面中的Edit RDBMS Relation按钮,设置student和locker数据表的关联字段,即指定这两个表之间通过哪个字段对应起来。如果这两个表有名字相同的字段,例如student表中有一个名位lockerid的字段,locker表中如果也有名为lockerid的字段,那么Jbuilder会自认为这两个表是通过lockid字段关联的。但是本例的locker表中使用的字段不是lockerid,而是id,所以此处必须手工指定数据表的关联字段。

6.2.6 在“Weblogic RDBMS Relation Editor”界面中在id字段和lockerid字段之间用鼠标拉一条直线,表示这两个表通过字段id和lockerid关联起来。

6.2.7 在工程窗口单击查看Locker表的Bean类,可以看到其中增加了针对关系字段的存取操作的代码:

    public abstract void setStudent(cmpsample.Student student);

    public abstract cmpsample.Student getStudent();

    相应的ejb-jar.xml和weblogic-cmp-rdbms-jar.xml文件中对关系的描述信息也添加了。

6.2.8 在文档窗口的EJB Designer中右键单击Locker项,选择Add/Method菜单项增加一个方法,该方法返回与Locker关联的student信息。

    修改该方法的设置如下:

      Method name: getStuInfo

      Return type: String

      Interface: remote

6.2.9 在文档窗口的EJB Designer中右键单击Locker项,选择Add/View Bean Source菜单项,修改getStuInfo()方法如下:

    public String getStuInfo()

    {

        String t = null;

        try

        {

            Student stuRemote = getStudent();

            t = "student id = " + stuRemote.getStuid() + ";student name = " +

                stuRemote.getStuname();

        }

        catch (Exception e)

        {}

        return t;

    }

6.2.10 重新编译、生成jar文件,然后使用Redeploy命令将新生成的Cmp.jar文件部署到Weblogic Server上。

6.2.11 建立Locker的客户端程序LockerTestClient1.java。

6.2.12 修改main()方法如下所示:

    public static void main(String[] args)

    {

        LockerTestClient1 client = new LockerTestClient1();

        client.findByPrimaryKey(new BigDecimal(2));

        client.getStuInfo();

    }

    该方法首先查找一个stuid为2的Student,然后调用getStuInfo()方法以获得该Student对应的Locker的信息。

6.2.13 运行该程序,验证结果。

七、通过Session Bean访问Entity Bean

    在前面给出的Entity Bean实例都是通过java客户端程序直接访问Entity Bean(通过Entity Bean的远程接口),在实际的应用系统开发中通常不采用这种做法,经常采用的是这样一种做法:建立一个Session Bean,该Session Bean中封装对Entity Bean的访问。而且访问时通过Entity Bean的本地接口进行以提高性能,客户端不与Entity Bean直接打交道,客户端通过Session Bean完成对Entity Bean的操作。这中做法其实是遵循了一种设计模式:Facade设计模式。

7.1 EJB引用

    在一个EJB中访问其他EJB,例如Session Bean facade要访问Entity Bean student,可以直接在facade中用“硬编码”实现,即在facade中通过Student的JNDI名字找到Home对象,然后获得对外接口(Remote接口或Local接口),完成方法调用。这种方式的缺点是显而易见的,因为这两个EJB被紧紧绑在一起,例如student有什么改动,例如改名字,那么facade就必须改代码(这也是为什么在《Entity Bean的运用(二)》中需要重新建立一个TestClient的原因)。

    J2EE采用这样一种方式解决此问题:在facade的部署描述文件中定义一个EJB引用,该项描述了对另一个EJB的引用,在facade的代码中只使用EJB引用的名字,EJB引用的名字是不变的,但是它所引用的内容是可变的,参见以下代码:

   <weblogic-enterprise-bean>

       <ejb-name>facade</ejb-name>

          <reference-descriptor>

             <ejb-reference-descriptor>

                 <ejb-ref-name>student</ejb-ref-name>

                 <jndi-name>Student</jndi-name>

             </ejb-reference-descriptor>

          </reference-descriptor>

       <jndi-name>facade</jndi-name>

     </weblogic-enterprise-bean>

     建立了EJB引用后,facade可以通过此引用获得要访问的EJB student的接口,参见以下代码:

    Context context = new InitialContext();

    Object ref = context.lookup("java:/comp/env/student");

    studentHome = (StudentHome)ref;

    在使用EJB引用时,作为lookup方法参数的完整的JNDI名字是“java:/comp/env/”+ EJB引用名,例如名为student的EJB引用,对应完整的JNDI名字是“java:/comp/env/student”。

7.2 EJB引用实例

7.2.1打开《Entity Bean的运用(一)》中建立的comSample工程,新建一个名为facade的Session Bean(可参看《SESSION BEAN篇》)。修改该Bean的如下信息:

    ★ Bean name: facade

Interface: remote

Session type: Stateless

7.2.2 在文档窗口“EJB Designer”中用鼠标右键单击facade,选择Open DD Editor菜单项。

7.2.3 在“DD Editor”界面中单击下方的EJB Local References选项卡。

7.2.4 在“EJB Local References”的设置界面中,单击Add按钮,然后在Name项后输入EJB引用的名字student,选中IsLink复选框(如果要引用的EJB是位于同一Jbuilder工程中则选种此项),Link项选择Student(要引用的EJB),其他项采用系统自动的设置即可。

7.2.5 在facade中增加一个方法getStuInfo(),该方法的功能是找到与参数(代表stuid)对应的Entity Bean Student,然后调用Student的方法getStuid()getStuname()。该方法的属性如下:

    Method name: getStuInfo

Return type: String

Input parameters: String stuid

Interface: remote

7.2.6 在facadeBean类中加入访问Student的代码。要访问Student,首先要获得StudentHome对象,这可以通过EJB引用获得。获得Home对象这部分代码要放在facadeejbCreate()方法和ejbActivate()方法中(即只要facade的实例一被建立或激活,就会获得StudentHome对象)。获得StudentHome对象后,在getStuInfo()方法中通过Home对象得到Student的本地接口(Local Interface),然后通过本地接口调用Student的方法。用以下代码替换facadeBean.java的代码:(灰色代码部分为手工添加的)

package cmpsample;

 

import java.math.*;

import javax.ejb.*;

import javax.naming.*;

 

public class facadeBean

    implements SessionBean

{

    SessionContext sessionContext;

    public Student student = null;

    private StudentHome studentHome = null;

    public void ejbCreate() throws CreateException

    {

        try

        {

            Context context = new InitialContext();

            Object ref = context.lookup("java:/comp/env/student");

            studentHome = (StudentHome) ref;

        }

        catch (Exception e)

        {

            e.printStackTrace();

        }

    }

 

    public void ejbRemove()

    {

        /**@todo Complete this method*/

    }

 

    public void ejbActivate()

    {

        try

        {

            Context context = new InitialContext();

            Object ref = context.lookup("java:/comp/env/student");

            studentHome = (StudentHome) ref;

        }

        catch (Exception e)

        {

            e.printStackTrace();

        }

 

    }

 

    public void ejbPassivate()

    {

        /**@todo Complete this method*/

    }

 

    public void setSessionContext(SessionContext sessionContext)

    {

        this.sessionContext = sessionContext;

    }

 

    public String getStuInfo(String stuid)

    {

        String strStu = null;

        try

        {

            student = studentHome.findByPrimaryKey(new BigDecimal(stuid));

            strStu = "The studentID is " + student.getStuid() + " Name is " +

                student.getStuname();

        }

        catch (Exception e)

        {}

        return strStu;

    }

}

7.2.7 重新编译EJB module,生成Cmp.jar文件,并部署到Weblogic Server上。

7.2.8 新建facade的客户端程序facadeTestClient1.java,利用该客户端程序访问facadegetStuInfo()方法。修改该客户端程序的main()方法如下:

    public static void main(String[] args)

    {

        facadeTestClient1 client = new facadeTestClient1();

        client.create();

        client.getStuInfo("2");

    }

7.2.9 编译运行该客户端程序,验证结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值