我直接粘贴过来的,不知道格式有没有变坏,如果看起来不整齐,可以到我的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关联
预备:编码基本pattern:
包名全部用小写字母,如ejbsample.session
类名用大小写结合的方法,且首字母大写,如EmployeeAction
变量名用大小写结合的方法,且首字母小写,如strName
模块级变量前面加上下划线,如_strName
数据库的设置:
安装好Oracle的客户端,保证与数据库服务器正确建立了连接。
JBuilder9的设置:
可以参考以前的文章。要点:oracle的库文件设定好;"Enterprise setup"设定好
WebLogic的设置:
启动Weblogic
打开控制台: http://localhost:7001/console
从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=pm
password=pm
dll=ocijdbc8
protocol=thin
(说明:用户名和密码换成自己的)
**Initial capacity
3
**Maximum capacity
10
(说明:最后别忘了将"Targets"里面"Available" apply到"Chosen"里面去)
配置一个"Tx Data Sources":
**Name:
ejbDS
**JNDI Name:
ejbDS
(说明:这就是在EJB设计的时候,要指定的数据源名称)
**Pool Name:
ejbDemo
(说明:这就是前面建立的connection pool的名称)
在JBuilder中建立"EJB module":
建议将.jar文件的保存位置可以放到weblogic的applications目录下:C:\bea\wlserver6.1\config\mydomain\applications
建好一个空的module之后,首先配置它的"DataSources"。右击"DataSources",选择"Import Schema from Database"。
首先选择"Driver"为"oracle.jdbc.driver.OracleDriver",然后URL填入"jdbc:oracle:thin:@172.16.3.100:1521:dev3","Username"和"Password"填入正确的(我这里分别填入"pm"、"pm"),"JNDI name"填入前面设定的"ejbDS".
ok之后,JBuilder就自动开始从数据库里面"Importing Schema"。如果没有出现这样的动作,就说明以前数据库的配置没有正确,再检查一遍。
在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类后面马上建立)
在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页面打交道的时候,它要发挥重要作用。)
下面就开始建立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();
}
}
写一个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>\r\n";
strDebugMsg = "<font color=red>" + strDebugMsg + "</font></p>\r\n"; strDebugMsg = str1 + str2 + str3 + str4 + strDebugMsg;
//out.writeChars( "[" + bartDateFormat.format(date) + "] " + strMsg + "\r\n");
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();
}
}
编辑完成实体bean
打开EbnEmployee、EbnEmployeeHome、EbnEmployeeBean,首先import一下:
import ejbsample.employee.EmployeeModel;
然后开始编辑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;
}
编辑完成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出去!!!
}
}
}
编制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!");
}
}
调试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分钟,时间超时,发布不成功”等等之类的提示。但是事实证明发布却是成功的,如果碰到这种情况,不理它就是了。
FAQ:
Q:得到这样的错误javax.naming.NameNotFoundException: Unable to resolve 'SbnEmployee' Resolved: '' Unresolved:'SbnEmployee' ; remaining name 'SbnEmployee'
A:没有正确发布EJB。请先启动weblogic,然后在JBuilder中右击ejb module,选择deploy。
Q:调试老通不过
A:重启weblogic,然后再试试吧。
Q:我改动了session bean,为什么没有效果?
A:修改EJB的任何一个部分,都要重新发布EJB才能生效。这个问题的症结很可能在这里。不过要记住,在JBuilder里面,此时要用Reploy这个选项,不要用Deploy。
Q:我在EJB里面System.out.println了一下,为什么看不到输出?
A:EJB的输出在weblogic里面。要注意的是,System.out.println的输出,有时候在JBuilder里面,有时候又在weblogic里面,有时候还可能到java的控制台里面(比如applet的输出,不过这是题外话了)。
Q:我的EJB写的都是正确的啊,为什么老是出现发布的错误?
A:试试:打开EJB module的属性,将“discriptors in module”里面的weblogic-ejb-jar.xml删除掉,然后重新发布。问题往往可能会在这里,特别是你用来调试的weblogic的版本变化的时候。
说明:这个条目可以放心删除,JBuilder在编译EJB的时候,会自动根据当前的设置加上这个条目。