EJB tutorial (推荐)

来源:互联网 发布:一对一办公软件培训班 编辑:程序博客网 时间:2024/05/20 19:30
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
我直接粘贴过来的,不知道格式有没有变坏,如果看起来不整齐,可以到我的blog去看看吧:)那里还有源文件的下载。
环境设定为:weblogic 6.1 + Jbuilder 9;
数据表为tmp_emp,要求用EJB的方式对这个表进行操作。字段为:
SQL> desc tmp_emp;Name     Type         Nullable Default Comments                             -------- ------------ -------- ------- ------------------------------------ ID       VARCHAR2(10)                  职员ID                               NAME     VARCHAR2(20) Y                职员名称                             JOB      VARCHAR2(20) Y                职员的工作名称                       HIREDATE DATE         Y                职员入职时间                         SAL      NUMBER(7,2)  Y                职员薪水                             COMM     VARCHAR2(20) Y                备注                                 DEPTID   VARCHAR2(10) Y                职员所属部门ID;和tmp_dept表的ID关联 

  1. 预备:编码基本pattern:
    包名全部用小写字母,如EJBsample.session
    类名用大小写结合的方法,且首字母大写,如EmployeeAction
    变量名用大小写结合的方法,且首字母小写,如strName
    模块级变量前面加上下划线,如_strName
  2. 数据库的设置:
    安装好Oracle的客户端,保证与数据库服务器正确建立了连接。
  3. JBuilder9的设置:
    可以参考以前的文章。要点:oracle的库文件设定好;"Enterprise setup"设定好
  4. WebLogic的设置:
    1. 启动Weblogic
    2. 打开控制台: http://localhost:7001/console
    3. 从JDBC的connection pools里面,"Configure a new JDBC connection pool",参数可以参考下面:
      **Name:EJBDemo(说明:这个可以任意取)**URL:jdbc:oracle:thin:@172.16.3.100:1521:dev3(说明:这个URL就是JDBC连接时的URL,格式可以参考JDBC的文档;dev3是数据库服务器172.16.3.100上的SID)**Driver classname:oracle.jdbc.driver.OracleDriver**Properties:user=pmpassword=pmdll=ocijdbc8protocol=thin(说明:用户名和密码换成自己的)**Initial capacity3**Maximum capacity10(说明:最后别忘了将"Targets"里面"Available" apply到"Chosen"里面去)
    4. 配置一个"Tx Data Sources":
      **Name:EJBDS**JNDI Name:EJBDS(说明:这就是在EJB设计的时候,要指定的数据源名称)**Pool Name:EJBDemo(说明:这就是前面建立的connection pool的名称)
  5. 在JBuilder中建立"EJB module":
    建议将.jar文件的保存位置可以放到weblogic的applications目录下:C:eawlserver6.1configmydomainapplications
    1. 建好一个空的module之后,首先配置它的"DataSources"。右击"DataSources",选择"Import Schema from Database"。
    2. 首先选择"Driver"为"oracle.jdbc.driver.OracleDriver",然后URL填入"jdbc:oracle:thin:@172.16.3.100:1521:dev3","Username"和"Password"填入正确的(我这里分别填入"pm"、"pm"),"JNDI name"填入前面设定的"EJBDS".
    3. ok之后,JBuilder就自动开始从数据库里面"Importing Schema"。如果没有出现这样的动作,就说明以前数据库的配置没有正确,再检查一遍。
  6. 在JBuilder的EJB设计器中设计实体bean:
    从JBuilder自动得到的数据表中,找到我们要操作的tmp_emp表。右击它,选择"Creat CMP 2.0 Entity Bean",JBuilder就会自动根据表的结构生成实体bean。如果对JBuilder自动生成的参数不满意,可以自己修改。我改动如下:
    **Bean name:EbnEmployee(说明:改动Bean name之后,Abstract schema name会自动改成一样的名字)**Interfaces:local**Classes and packages:EJBsample.employee.entity(说明:a)包名全部用小写 b)在JBuilder的Classes and packages定义页面,只需要输入default package为EJBsample.employee.entity,其它的项JBuilder会自动填好)**增加3个方法(当然,你如果需要添加方法,可以随时到JBuilder的EJB设计器里面来添加):  void setModel ( EmployeeModel model ) 方法(interface:local)  EmployeeModel getModel () 方法 (interface :local )  EJBCreate( EmployeeModel model ) 方法 (interface :local home )(说明:EmployeeModel类后面马上建立)
  7. 在JBuilder的EJB设计器中设计session bean:
    在JBuilder的EJB设计容器中右击,选择新建session bean。修改参数如下:
    **Bean name: SbnEmployee**Session type: stateless**interfaces: remote**class--default package: EJBsample.employee.session**增加如下方法(当然,你如果需要添加方法,可以随时到JBuilder的EJB设计器里面来添加):  EmployeeModel insert ( EmployeeModel model ) 方法 (interfaces: remote )  EmployeeModel update ( EmployeeModel model ) 方法 (interfaces: remote )  boolean del ( String pk ) 方法 ( interfaces: remote )  EmployeeModel findByPk ( String pk ) 方法 ( interfaces: remote )  boolean delBatch ( String[] sid ) 方法 ( interfaces:remote )  java.util.ArrayList queryBySql ( String strSql ) 方法 ( interfaces:remote )  (说明:我们可以看到EmployeeModel类的使用是无处不在的。事实上,EmployeeModel里面包装了所有的页面显示元素,  在与jsp页面打交道的时候,它要发挥重要作用。)
  8. 下面就开始建立EmployeeModel类:
    新建一个class,命名为EmployeeModel,package定义为EJBsample.employee,基类选择为java.io.Serializable.内容如下:
    package EJBsample.employee;import java.io.Serializable;/** * Title: (no title) * Description: 一般来说,xxModel类可以看作对jsp页面所有显示元素的包装。它将是主要与jsp页面打交道的类 * Copyright: Copyright (c) 2003 * Company: Ebuilds * @author Alex * @version 1.0 */public class EmployeeModel implements Serializable {    private String    _strID;          //职员ID    private String    _strName;        //职员名称    private String    _strJob;         //职员的工作名称    private java.sql.Date          _dtHireDate;     //职员入职时间    private double    _dSal;           //职员薪水    private String    _strComm;        //备注    private String    _strDeptID;      //职员所属部门ID;和tmp_dept表的ID关联    //设定属性、读取属性 开始    public String getID () {        return _strID;    }    public void setID ( String in ) {        _strID = in;    }    public String getName () {        return _strName;    }    public void setName ( String in ) {        _strName = in;    }    public String getJob () {        return _strJob;    }    public void setJob ( String in ) {        _strJob = in;    }    public java.sql.Date getHireDate () {        return _dtHireDate;    }    public void setHireDate ( java.sql.Date in ) {        _dtHireDate = in;    }    public double getSal () {        return _dSal;    }    public void setSal ( double in ) {        _dSal = in;    }    public String getComm () {        return _strComm;    }    public void setComm ( String in ) {        _strComm = in;    }    public String getDeptID () {        return _strDeptID;    }    public void setDeptID ( String in ) {        _strDeptID = in;    }    //设定属性、读取属性 结束    public void setModel ( EmployeeModel in ) {        _strID = in.getID();        _strName = in.getName();        _strJob = in.getJob();        _dtHireDate = in.getHireDate();        _dSal = in.getSal();        _strComm = in.getComm();        _strDeptID = in.getDeptID();    }    public EmployeeModel() {    }    public static void main(String[] args) {        EmployeeModel employeeModel1 = new EmployeeModel();    }}
  9. 写一个EJB的公共类:EJBCommon.java。非常重要的代码!
    package EJBsample;/** * Title: (no title) * Description: 这是写EJB的时候需要用到的公共类,比如JNDI名称、取home接口。当进行大型开发,有很多EJB的时候,这个类是很有必要的 * Copyright: Copyright (c) 2003 * Company: Ebuilds * @author Alex * @version 1.0 */import java.util.*;import javax.naming.*;import javax.EJB.*;import javax.rmi.PortableRemoteObject;import javax.naming.InitialContext;import javax.naming.NamingException;import weblogic.jndi.Environment;import javax.sql.*;import java.sql.*;public class EJBCommon {    //这里存放所有的JNDI名。如果JNDI名很多,建议可以将它们单独放到一个文件中去。    //说明:JNDI名在这里找到:JB的"project content"中,双击"EbnEmployee",可以看到"Local Home JNDI Name",就是了。    public static final String E_EMPLOYEE_JNDI = "EbnEmployee";    public static final String S_EMPLOYEE_JNDI = "SbnEmployee";    public static final String DATASOURCE_JNDI = "EJBDS";    //以下是取home接口相关的函数    private static Context context = null;    /**     * 取得InitialContext,供后面的取home接口使用     * @return     * @throws NamingException     */    protected static Context getInitialContext() throws NamingException {        String user = null;        String password = null;        Properties properties = null;        try {            properties = new Properties();            properties.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");            if (user != null) {                properties.put(Context.SECURITY_PRINCIPAL, user);                properties.put(Context.SECURITY_CREDENTIALS, password == null ? "" : password);            }            return new InitialContext(properties);        }        catch(NamingException e) {            throw e;        }    }    /**     *用于取得远程home接口。一般来说,session bean的接口是远程的(不是local),所以,取得session bean的home接口要用到这个函数     * @param lookupName     * @param homeClass     * @return     */    public static Object getRemoteEJBHome(String lookupName, Class homeClass) throws NamingException {        try {            if (context==null) {                context = getInitialContext();            }            Object home = PortableRemoteObject.narrow(                                context.lookup(lookupName),                                homeClass);            return home;        } catch (NamingException ne) {            //throw new EJBException(ne.getMessage());            throw ne;        }    }    /**     * 用于取得本地home接口。一般来说,实体bean的接口是本地(local)的,所以,取得实体bean的home接口要用到这个函数。     * @param lookupName     * @return     */    public static Object getLocalEJBHome(String lookupName) throws NamingException{        try {            if (context==null) {                context = getInitialContext();            }            Object home = context.lookup(lookupName);            return home;        } catch (NamingException ne) {            //throw new EJBException(ne.getMessage());            throw ne;        }    }    //下面的是关于数据库的操作。一个重要的,用完了getConnection()之后,记得释放connection!    /**     * 从定义好的datasource里面取出一个connection     * @return     */    public static Connection getConnection() throws NamingException, SQLException{        Connection con=null;        try {            if ( context == null ){                context = getInitialContext();            }            DataSource datasource=(DataSource)context.lookup( DATASOURCE_JNDI );            con = datasource.getConnection();        } catch (NamingException ex) {            throw ex;        } catch (SQLException ex) {            throw ex;        }        return con;    }    /**     * 这是取连接的远程版本。但是好像不需要用它。     * @return     */    public static Connection getConnection_remote() throws NamingException, SQLException{        try {            if (context==null) {                context = getInitialContext();            }            DataSource ds = (DataSource)PortableRemoteObject.narrow(                                context.lookup(DATASOURCE_JNDI),                                DataSource.class);            return ds.getConnection();        } catch (NamingException ne) {            //throw new EJBException(ne.getMessage());            throw ne;        } catch (SQLException e) {            //throw new EJBException(e.getMessage());            throw e;        }    }    /**     * 作用:用html格式将strmsg输入到c:strlogfile文件中去     * 将会输出类似这样的语句:     * 

    [2003-四月-29 04:44:03] 被调试文件:vwDetail.jsp 被调试函数:(开始设置projectID) 调试描述:
    取得的projectID为ERPPM200212110000000658310000E8E7FF69

    * * Added by daihua 2003-4-29 11:16 * @param strMsg */ public static void logOneLineToFile ( String strLogFile, String strDebugFileName, String strDebugFuncName, String strDebugMsg ){ //如果不需要debug输出的话,直接返回 /*if ( ! debuggingOn ) return; */ java.io.File fd = new java.io.File ( "c:/debug" ); if ( !fd.exists() ) { fd.mkdirs(); } //根据当前的日期自动生成debug的文件名,比如:c:20030506debug.html /*SimpleDateFormat sdfF = new SimpleDateFormat ( "yyyyMMdd" ); String strLogFileName = "c:/debug/" + sdfF.format( new Date() ) + "debug.html" ; */ String strLogFileName = "c:/debug/" + strLogFile; //还是由程序指定debug的文件名 java.text.SimpleDateFormat bartDateFormat = new java.text.SimpleDateFormat("yyyy-MMMM-dd hh:mm:ss"); java.util.Date date = new java.util.Date(); java.io.FileWriter out = null; try { java.io.File f = new java.io.File ( strLogFileName ); if ( !f.exists() ){ f.createNewFile(); } //out = new RandomAccessFile ( f, "rw" ); out = new java.io.FileWriter ( strLogFileName, true ); //To be ready for append //out.seek( out.length() ); String str1 = "<p style="font-size:10.5pt; line-height:15pt">" + "<font color="#999999">[" + bartDateFormat.format(date) + "] 被调试文件:</font>"; String str2 = "<font color="#3333FF">" + strDebugFileName + "</font>"; String str3 = "<font color="#999999"> 被调试函数:</font><font color="#3333FF">" + strDebugFuncName + "</font>"; String str4 = "<font color="#999999"> 调试描述:</font><br>"; strDebugMsg = "<font color=red>" + strDebugMsg + "</font></p>"; strDebugMsg = str1 + str2 + str3 + str4 + strDebugMsg; //out.writeChars( "[" + bartDateFormat.format(date) + "] " + strMsg + ""); out.write( strDebugMsg ); }catch ( Exception e ) { e.printStackTrace(); } finally{ try{ if ( out != null ) out.close(); }catch ( Exception ex ){ ex.printStackTrace(); } } } public EJBCommon() { } public static void main(String[] args) { EJBCommon EJBCommon1 = new EJBCommon(); }}
  10. 编辑完成实体bean
    1. 打开EbnEmployee、EbnEmployeeHome、EbnEmployeeBean,首先import一下:
      import EJBsample.employee.EmployeeModel;
    2. 然后开始编辑EbnEmployeeBean,完成EJB设计器里面设计的函数
      • void setModel(EmployeeModel model)函数:
            public void setModel(EmployeeModel model) {        this.setId ( model.getID() );        this.setName ( model.getName() );        this.setJob ( model.getJob() );        this.setHiredate ( model.getHireDate() );        this.setSal ( model.getSal() );        this.setComm ( model.getComm() );        this.setDeptid ( model.getDeptID() );    }
      • EmployeeModel getModel()函数
            public EmployeeModel getModel() {        EmployeeModel data = new EmployeeModel();        data.setID( this.getId());        data.setName( this.getName());        data.setJob( this.getJob() );        data.setHireDate( this.getHiredate() );        data.setSal( this.getSal() );        data.setComm( this.getComm() );        data.setDeptID( this.getDeptid() );        return data;    }
      • java.lang.String EJBCreate(EmployeeModel model)
            public java.lang.String EJBCreate(EmployeeModel model) throws CreateException {     //说明:这个函数非常重要,每次创建实体bean的时候,都会自动调用EJBCreate,所以如果没有完成这个函数的话,实体bean中将无法赋值        setModel ( model );        return null;    }
  11. 编辑完成session bean类SbnEmployeeBean.java,如下
    package EJBsample.employee.session;import javax.EJB.*;import EJBsample.employee.EmployeeModel;import EJBsample.EJBCommon;import java.util.ArrayList;import EJBsample.employee.entity.*;import javax.naming.NamingException;import java.sql.*;import java.rmi.*;public class SbnEmployeeBean implements SessionBean {    SessionContext sessionContext;    public void EJBCreate() throws CreateException {        /**@todo Complete this method*/    }    public void EJBRemove() {        /**@todo Complete this method*/    }    public void EJBActivate() {        /**@todo Complete this method*/    }    public void EJBPassivate() {        /**@todo Complete this method*/    }    public void setSessionContext(SessionContext sessionContext) {        this.sessionContext = sessionContext;    }    public EmployeeModel insert(EmployeeModel model) throws CreateException,NamingException,RemoteException{        try {            //利用EJBCommon类得到实体bean的home接口            EbnEmployeeHome objHome = (EbnEmployeeHome) EJBCommon.getLocalEJBHome( EJBCommon.E_EMPLOYEE_JNDI );            EbnEmployee objRemote=objHome.create(model);            return model;        }        catch(CreateException e) {            throw e;        }        catch(NamingException e) {            throw e;        }    }    public EmployeeModel update(EmployeeModel model) throws FinderException, NamingException, RemoteException {        try {            //利用EJBCommon类得到实体bean的home接口            EbnEmployeeHome objHome = (EbnEmployeeHome) EJBCommon.getLocalEJBHome(EJBCommon.E_EMPLOYEE_JNDI);            EbnEmployee objLocal = objHome.findByPrimaryKey(model.getID());            //调用model的取属性函数,将实体bean更新            //objLocal.setModel(model);  //不能这么写。具体为什么,我也不知道。好像没有道理啊            objLocal.setName( model.getName() );            objLocal.setJob( model.getJob() );            objLocal.setHiredate( model.getHireDate() );            objLocal.setSal( model.getSal() );            objLocal.setComm( model.getComm() );            objLocal.setDeptid( model.getDeptID() );            return model;        }        catch (FinderException e) {            throw e;        }        catch (NamingException e) {            throw e;        }    }    public boolean del(String pk) throws RemoveException,FinderException,EJBException,NamingException ,RemoteException {        try {            //利用EJBCommon类得到实体bean的home接口            EbnEmployeeHome objHome = (EbnEmployeeHome) EJBCommon.getLocalEJBHome(                EJBCommon.E_EMPLOYEE_JNDI);            EbnEmployee objLocal = objHome.findByPrimaryKey(pk);            objLocal.remove();            return true;        }        catch (RemoveException e) {            throw e;        }        catch (FinderException e) {            throw e;        }        catch (EJBException e) {            throw e;        }        catch (NamingException e) {            throw e;        }    }    public EmployeeModel findByPk(String pk) throws FinderException, NamingException, RemoteException {        try {            //利用EJBCommon类得到实体bean的home接口            EbnEmployeeHome objHome = (EbnEmployeeHome) EJBCommon.getLocalEJBHome(EJBCommon.E_EMPLOYEE_JNDI);            EmployeeModel model = new EmployeeModel();            EbnEmployee objLocal = objHome.findByPrimaryKey(pk);            model = objLocal.getModel();            return model;        }        catch (FinderException e) {            throw e;        }        catch (NamingException e) {            throw e;        }    }    public boolean delBatch(String[] sid) throws NamingException, SQLException,RemoteException{        String[] sID = null;        sID = sid;        String sql = "delete FROM tmp_emp WHERE ID='" ; //Note: statmachine is the table name connected with our work        String id = new String();        Connection conn = null;        Statement st = null;        boolean b = false;        try {            conn = EJBCommon.getConnection();            conn.setAutoCommit(false);            st = conn.createStatement();            for(int i = 1;i <= sID.length ;i++ ){                id = sID[i-1];                st.execute(sql + id + "'");            }            conn.commit();            b = true;            return b;        }catch ( NamingException e ){            throw e;        }catch(SQLException e){            System.err.print( "delBatch() function error: concerning with database");            try {                conn.rollback();            }catch(SQLException sqle){                throw sqle;            }            throw e;        }finally{            try {                st.close();                conn.close();            }catch(SQLException e){                throw e;            }            //return b;  //说明:不要在finally里面return,否则,捕捉到的错误不会throw出去!!!        }    }    public java.util.ArrayList queryBySql(String strSql)  throws NamingException, SQLException,RemoteException{        ArrayList arrayList = null;        EmployeeModel item;        Connection conn = null;        Statement st = null;        ResultSet rs = null;        try {            conn=EJBCommon.getConnection();            st=conn.createStatement();            rs=st.executeQuery("SELECT * FROM tmp_emp WHERE " + strSql); //Of course, you can change the sql statement according your condition            System.out.println("queryBySql函数的sql=" + "SELECT * FROM tmp_emp WHERE " + strSql);            arrayList = new ArrayList();            while (rs.next()) {                item=new EmployeeModel();                //从数据库里面读取值                item.setID( rs.getString( "ID" ));                item.setName( rs.getString( "NAME" ));                item.setJob( rs.getString( "JOB" ));                item.setHireDate( rs.getDate( "HIREDATE" ));                item.setSal( rs.getDouble( "SAL" ));                item.setComm( rs.getString( "COMM" ));                item.setDeptID( rs.getString( "DEPTID" ));                arrayList.add(item);            }            if ( arrayList.size() <= 0 ){                return null;            }else{                return arrayList;            }        }catch(SQLException e){            System.out.println("queryBySql函数出现了SQL错误:" + e.toString() + ",将返回的ArrayList设置为Null");            throw e;        }catch(NamingException e1){            throw e1;        }        finally{            System.out.println("queryBySql函数进入finally子块,关闭连接");            try {                if (rs!=null)                    rs.close();            }catch(SQLException e){                throw e;            }            try {                if (st!=null)                    st.close();            }catch(SQLException e){                throw e;            }            try {                if (conn!=null)                    conn.close();            }catch(SQLException e){                throw e;            }            //return arrayList;  //说明:不要在finally里面return,否则,捕捉到的错误不会throw出去!!!        }    }}
  12. 编制EmployeeAction.java。这个类包装了EJB,是与jsp页面打交道的类。(这个action类,以及前面的model类,是两个主要和jsp页面打交道的类;而action类包装了EJB,model类包装了jsp页面显示元素)
    新建一个class,命名为EmployeeAction,package定义为EJBsample.employee。内容如下:
    package EJBsample.employee;/** * Title: (no title) * Description: xxAction类基本上是EJB的包装。 * Copyright: Copyright (c) 2003 * Company: Ebuilds * @author Alex * @version 1.0 */import EJBsample.SequenceUtil;import EJBsample.EJBCommon;import EJBsample.employee.EmployeeModel;import EJBsample.employee.entity.*;import EJBsample.employee.session.*;import javax.EJB.*;import javax.naming.NamingException;import java.rmi.RemoteException;import java.util.ArrayList;import java.sql.*;public class EmployeeAction {    /**     * 传入一个model(没有ID这个属性),自动加一个唯一的ID,然后往数据库里面加一条记录     * @param model     * @return     * @throws NamingException     * @throws RemoteException     * @throws CreateException     */    public EmployeeModel add( EmployeeModel model ) throws NamingException, RemoteException,        CreateException {        model.setID(SequenceUtil.getUniteCode()); //getUniteCode()的作用是:得到一个唯一的ID号。可以随便怎么写这个函数,比如可以用当前的时间作为ID:getTime();或者用网卡物理地址加上当前时间等等        try {            SbnEmployeeHome objHome = (SbnEmployeeHome) EJBCommon.                                      getRemoteEJBHome(EJBCommon.                S_EMPLOYEE_JNDI, SbnEmployeeHome.class);            SbnEmployee objRemote = objHome.create();            //从上面的两行代码可以看出session bean编码的格式:首先得到home接口;然后调用create()函数得到接口            return objRemote.insert(model);        }        //关于错误处理:千万不要在catch里面什么都不做,要么把catch到的错误throw出去,要么显示一些信息出来;否则的话,程序将会无法调试!        catch (NamingException e) {            throw e;        }        catch (RemoteException e) {            throw e;        }        catch (CreateException e) {            throw e;        }    }    /**     * 根据传入的主键,删除数据库里面的一条记录。     * @param strPk     * @return     * @throws NamingException     * @throws RemoteException     * @throws CreateException     */    public boolean delete(String strPk) throws NamingException, RemoteException, CreateException,RemoveException,FinderException {        try {            SbnEmployeeHome objHome = (SbnEmployeeHome) EJBCommon.                                      getRemoteEJBHome(EJBCommon.                S_EMPLOYEE_JNDI, SbnEmployeeHome.class);            SbnEmployee objRemote = objHome.create();            boolean b = objRemote.del(strPk);            return b;        }        //关于错误处理:必须这么一个一个地catch错误,然后throw出去!        catch (NamingException e) {            throw e;        }        catch (RemoteException e) {            throw e;        }        catch (CreateException e) {            throw e;        }        catch (RemoveException e) {            throw e;        }        catch (FinderException e) {            throw e;        }    }    /**     * 根据传入的model,更新数据库里面的一条记录     * @param model     * @return     * @throws NamingException     * @throws RemoteException     * @throws CreateException     */    public EmployeeModel update(EmployeeModel model) throws NamingException, RemoteException, CreateException,FinderException    {        try {            SbnEmployeeHome objHome = (SbnEmployeeHome) EJBCommon.                                      getRemoteEJBHome(EJBCommon.                S_EMPLOYEE_JNDI, SbnEmployeeHome.class);            SbnEmployee objRemote = objHome.create();            return objRemote.update(model);        }        catch (NamingException e) {            throw e;        }        catch (RemoteException e) {            throw e;        }        catch (CreateException e) {            throw e;        }        catch (FinderException e) {            throw e;        }    }    /**     * 根据传入的主键,返回一个model     * @param strPk     * @return     * @throws NamingException     * @throws RemoteException     * @throws CreateException     */    public EmployeeModel findByPk(String strPk)  throws NamingException, RemoteException, CreateException,FinderException    {        try {            SbnEmployeeHome objHome = (SbnEmployeeHome) EJBCommon.                                      getRemoteEJBHome(EJBCommon.                S_EMPLOYEE_JNDI, SbnEmployeeHome.class);            SbnEmployee objRemote = objHome.create();            return objRemote.findByPk(strPk );        }        catch (NamingException e) {            throw e;        }        catch (RemoteException e) {            throw e;        }        catch (CreateException e) {            throw e;        }        catch (FinderException e) {            throw e;        }    }    /**     * 根据传入的sql(注意不是完整的sql语句),得到所有满足条件的model,放到一个ArrayList里面返回     * @param sql     * @return     * @throws NamingException     * @throws RemoteException     * @throws CreateException     */    public ArrayList queryBySql(String sql)  throws NamingException, RemoteException, CreateException,SQLException    {        try {            SbnEmployeeHome objHome = (SbnEmployeeHome) EJBCommon.                                      getRemoteEJBHome(EJBCommon.                S_EMPLOYEE_JNDI, SbnEmployeeHome.class);            SbnEmployee objRemote = objHome.create();            return objRemote.queryBySql(sql);        }        catch (NamingException e) {            throw e;        }        catch (RemoteException e) {            throw e;        }        catch (CreateException e) {            throw e;        }        catch (SQLException e) {            throw e;        }    }    /**     * 根据传入的主键数组,批量删除记录     * @param sId     * @return     * @throws NamingException     * @throws RemoteException     * @throws CreateException     */    public boolean deleteBatch(String[] sId) throws NamingException, RemoteException, CreateException{        boolean b = false;        try {            SbnEmployeeHome objHome = (SbnEmployeeHome) EJBCommon.                                      getRemoteEJBHome(EJBCommon.                S_EMPLOYEE_JNDI, SbnEmployeeHome.class);            SbnEmployee objRemote = objHome.create();            b = objRemote.delBatch(sId);        }        catch (NamingException e) {            throw e;        }        catch (RemoteException e) {            throw e;        }        catch (CreateException e) {            throw e;        }        finally{            return b;        }    }    public EmployeeAction() {    }    public static void main(String[] args) {        EmployeeAction action = new EmployeeAction();        //以下是调试代码。注意:最好在EJB发布到weblogic之前,将session bean里面的所有方法调试一遍,        //确保不会有比较低级的错误。否则,如果到了jsp页面再去调试,无疑是nightmare        EmployeeModel data = new EmployeeModel();        //说明:1)要调试的话,只要将“测试xx方法”前面加上/就可以了。        //      2)有时候EJB运行比较慢,JBuilder里面半天没有反应。这是可以在前面的方法里面加一些        //         输出语句,让你知道程序是在正确运行。        //*测试add()方法        for (int i = 0; i < 6; i++) {            data.setName("name" + i);            data.setJob("job1");            data.setHireDate(java.sql.Date.valueOf( "2003-07-21") );            try {                action.add(data);            }            catch (Exception e) {                e.printStackTrace();            }        }        //**/        /*测试delete()方法         try {             action.delete("ID_2003072504CB077B81059114950140"); //这个主键的值是都数据库里面找的。         }         catch (Exception e) {             e.printStackTrace();         }        //*/        /*测试deleteBatch()方法        String[] strSID = { "ID_2003072504CB077B81059116383421", "ID_2003072504CB077B81059116474625", "ID_2003072504CB077B81059116477218" };        try {            action.deleteBatch( strSID );        }        catch ( Exception e ) {            e.printStackTrace();        }        //*/        /*测试findByPk()方法        String strPK = "ID_2003072504CB077B81059116477328";        try{            data = action.findByPk( strPK );            System.out.println("找到的name=" + data.getName());        }        catch ( Exception e ) {            e.printStackTrace();        }        //*/        /*测试queryBySql()方法        String strSql = "job1='job1'";        ArrayList alRet = null;        try{            alRet = action.queryBySql( strSql );            if ( alRet != null && alRet.size() > 0) {                for ( int i = 0; i < alRet.size(); i ++ ){                    data = ( EmployeeModel ) alRet.get( i );                    System.out.println("找到符合条件的第" + (i+1) + "个记录,name=" + data.getName());                }            }else{                System.out.println("没有找到记录");            }        }        catch ( Exception e ) {            e.printStackTrace();        }        //*/        /*调试update()函数        String strPK1 = "ID_2003072504CB077B81059118072859";        try{            data = action.findByPk( strPK1 );            System.out.println("找到的旧的name=" + data.getName());            data.setName( "new name" );            action.update( data );        }        catch ( Exception e ) {            e.printStackTrace();        }        //*/        System.out.println("*********Final!");    }}
  13. 调试EJB
    调试方法是运行EmployeeAction。注意在运行之前,必须启动weblogic,并且保证EJB已经正确发布了。事实上,EJB的发布也要调试很长时间的。调试注意事项:
    • 调试EJB是很麻烦的,而且非常耗费内存。如果内存不是512M以上,就等着痛苦降临吧:)我现在就是这样,简直有砸电脑的欲望。
    • 有时候,所有的步骤都正确,但是总是有一些奇怪的错误。(比如我写这个例子的时候)这时,一般先shutdown weblogic,然后将weblogic目录下的所有临时目录(一般以TMP开头)全部删掉,然后重启一下weblogic。问题往往能够得到解决。不要问为什么,估计bea公司的人也不知道。
    • 在JBuilder中,最好把EJB module的"Always creating JAR when building the project"去掉。免得每次都要重复编译EJB的.jar文件。
    • 有时候编译出来的.jar文件很大(比如1M、2M;一般几十、几百KB是比较正常的),就要看EJB module的属性设置是否正确。主要是content是否包含所有的类,一般应该选择只包含用到的类。
    • 用JBuilder发布的时候,有时候可能会碰到它提示“超过4分钟,时间超时,发布不成功”等等之类的提示。但是事实证明发布却是成功的,如果碰到这种情况,不理它就是了。
  14. FAQ:
    1. Q:得到这样的错误javax.naming.NameNotFoundException: Unable to resolve 'SbnEmployee' Resolved: '' Unresolved:'SbnEmployee' ; remaining name 'SbnEmployee'
      A:没有正确发布EJB。请先启动weblogic,然后在JBuilder中右击EJB module,选择deploy。
    2. Q:调试老通不过
      A:重启weblogic,然后再试试吧。
    3. Q:我改动了session bean,为什么没有效果?
      A:修改EJB的任何一个部分,都要重新发布EJB才能生效。这个问题的症结很可能在这里。不过要记住,在JBuilder里面,此时要用Reploy这个选项,不要用Deploy。
    4. Q:我在EJB里面System.out.println了一下,为什么看不到输出?
      A:EJB的输出在weblogic里面。要注意的是,System.out.println的输出,有时候在JBuilder里面,有时候又在weblogic里面,有时候还可能到java的控制台里面(比如applet的输出,不过这是题外话了)。
    5. Q:我的EJB写的都是正确的啊,为什么老是出现发布的错误?
      A:试试:打开EJB module的属性,将“discriptors in module”里面的weblogic-EJB-jar.xml删除掉,然后重新发布。问题往往可能会在这里,特别是你用来调试的weblogic的版本变化的时候。
      说明:这个条目可以放心删除,JBuilder在编译EJB的时候,会自动根据当前的设置加上这个条目。



<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
<script type="text/javascript"><!--google_ad_client = "pub-2947489232296736";/* 160x600, 创建于 08-4-23MSDN */google_ad_slot = "4367022601";google_ad_width = 160;google_ad_height = 600;//--></script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>