如何实现EJB的抽象、继承(有项目经验者请进)

小弟正在做一个J2EE项目,遇到这样的问题:
有几个表,结构差不多,操作也差不多,如果是不用EJB,直接就可以抽象出一个父类,然后其他类继承就可以了。
在EJB 模块中,我采用SessionBean facade模式,我做了两个抽象类:
一个是EB的抽象类,一个是SB的抽象类。发布成功。
代码示例:
User为实体bean Student 和 Teacher的抽象类,是一个简单的类,包括了一些get,set的定义,Student和Teacher的Local接口中相应进行修改:
public interface Student extends EJBLocalObject,User
public interface Teacher extends EJBLocalObject,User

同时,我修改Student和Teacher bean Home接口中的各方法的返回值类型,统一为User
public User create(String sysid) throws CreateException;
public User findByPrimary(String id);
==========================
session bean :StudentController中的方法:
==========================
public User getUserById(String _sId) throws
FinderException {
Context cxt = new InitialContext("Student");
Object o = cxt.lookup("Student");
StudentHome stuHome = (StudentHome) o ;
return stuHome.findByPrimary(_sId);
}
=====================


但是事情没有我想的那么简单,在jsp中调用session bean的时候,出现了
java.rmi.ServerException: RuntimeException; nested exception is:
java.lang.ClassCastException
的错误。

==========================
由于第一次做这样的项目,而且在别的地方没有看到过这样的用法,我不知我的想法是否可行。如果可行,是什么地方出了问题。还请大家指点

ejb不能继承

不能继承?那你是如何解决这种问题的?重复Copy代码吗?

你做的是实体Bean,实体Bean其实用不着继承,你可以将你的继承关系反映在Model上。

楼上这位,能解释一下吗,如何把继承关系反映到Moudle上?

EJB可以继承,我在一个项目中使用过。
不过,我觉得在EJB中使用继承不是个好办法。

>如何把继承关系反映到Moudle上?
即是面向Model模型设计,UML中我们总是设计出Model的类图后,再实现实体化。可参考我的书籍或UML方面设计。

那对于我手头的这个示例,怎样才能使结构更合理,代码重用性更高,各位有什么好建议呢?

个人认为EntityBean没有必要继承的,因为所有的EB除了findXXX和get/set之外都差不多。
SessionBean继承没有问题,参考一下PetStore

>那对于我手头的这个示例,怎样才能使结构更合理,代码重用性更高,各位有什么好建议呢?

看了你的方案,你将用户user 学生 教师各建立一个表,其实你没有看到他们的一致性,他们都是可以用一个实体Bean User来代表,不同的是角色,因此,你只要再建一个role表,用以描述User中数据的身份:是学生还是教师等。

这样,你就可以建立一个基于User表和Role表的可重用的EJB组件,应用中不同项目中。我的www.jdon.com/my中就是采取这种思路设计,网上支付购买教材后的用户角色从普通user变成了Student,这套软件可以重用在很多项目中,不同的只是数据表的数据和角色定义,角色定义可以通过web.xml和role数据表进行数据修改。

关于基于容器的角色安全机制实现可参考我的书籍。

嗯。。banq的这个建议有点道理。
虽然在我的实际需求中,Teacher和Student 还有不少有区别的地方,但是你的建议给了我一个提示。共同的东西,可以抽象出来,包括在数据库端。
我现在的想法是,这种问题,在数据库端,可以建立三个表,一个是UserInfo,保存用户的基本信息。因为不同的用户,基本信息的描述指标都差不多。然后再建立一个Teacher表和Student表跟UserInfo表进行关联。
同时,建立两个视图,ViewTeacher和ViewStudent,以方便访问。
然后,在持久化层,对以上五个表进行映射。
业务层,对于增删改的操作,对应表实体bean,对于查询显示,对应视图实体bean。
感觉这样,结构是比较清晰。唯一不太好的是,进行增删改的时候,会涉及多表操作,需要使用事务,麻烦了一点。
不知banq兄对我的想法有什么意见。

EJB不能继承。此种观点,偶不敢苟同!

要是觉得我在说大话,你如果用JBuilder开发EJB,不知道你注意到没有,在EJB Designer模式下每当你用左键选择一个SessionBean也好,还是Entity Bean也好都会有一个Bean properties,里面有个按钮“Inheritance”,那里可以指定所要继承的父类。如果EJB不能继承,它提供一个这个功能干什么呢?

EJB当然可以继承,但是CMP没有必要,因为是数据库的再现。至于数据库,按照3NF做就可以了。即便CMP之间有共同之处也不必继承,例如:
ACMP有getUserName方法,BCMP有getTeacherName方法,难道我们抽象出一个EJB,包含getString方法?^_^

这是PetStore实现继承的例子:


/**
* Session Bean implementation for EJBClientController EJB.
* See the StateMachine for more details.
*/

public class ShoppingClientControllerEJB extends EJBClientControllerEJB {
private ShoppingClientFacadeLocal clientFacade = null;

public void ejbCreate() {
sm = new StateMachine(this, sc);
sm.setAttribute(
"shoppingClientFacade", getShoppingClientFacade());
}

public ShoppingClientFacadeLocal getShoppingClientFacade() {
if (clientFacade == null) {
try {
InitialContext ic = new InitialContext();
Object o = ic.lookup(
"java:comp/env/ejb/controller/ClientFacade");
ShoppingClientFacadeLocalHome home =(ShoppingClientFacadeLocalHome)o;
clientFacade = home.create();
} catch (javax.ejb.CreateException cx) {
throw new GeneralFailureException(
"ShoppingClientControllerEJB: Failed to Create ShoppingClientFacade: caught " + cx);
} catch (javax.naming.NamingException nx) {
throw new GeneralFailureException(
"ShoppingClientControllerEJB: Failed to Create ShoppingClientFacade: caught " + nx);
} catch (java.rmi.RemoteException rx) {
throw new GeneralFailureException(
"ShoppingClientControllerEJB: Failed to Create ShoppingClientFacade: caught " + rx);
}
}
return clientFacade;
}

}
/**
* Session Bean implementation for EJBClientController EJB.
* See the StateMachine for more details.
*/

public class EJBClientControllerEJB implements SessionBean {

protected StateMachine sm;
protected SessionContext sc;

public EJBClientControllerEJB() {}


public void ejbCreate() {
sm = new StateMachine(this, sc);
}

/** returns an EventResponse */

public EventResponse processEvent(Event ev)
throws EventException {
return (sm.processEvent(ev));
}

public void setSessionContext(SessionContext sc) {
this.sc = sc;
}

public void ejbRemove() {
sm = null;
}

public void ejbActivate() {}

public void ejbPassivate() {}
}

> 小弟正在做一个J2EE项目,遇到这样的问题:
> 有几个表,结构差不多,操作也差不多,如果是不用EJB,直?> 就可以抽象出一个父类,然后其他类继承就可以了。
> 在EJB 模块中,我采用SessionBean
> n facade模式,我做了两个抽象类:
> 一个是EB的抽象类,一个是SB的抽象类。发布成功。
> 代码示例:
> User为实体bean Student 和
> Teacher的抽象类,是一个简单的类,包括了一些get,set的?> 义,Student和Teacher的Local接口中相应进行修改:
> public interface Student extends EJBLocalObject,User
>
> public interface Teacher extends EJBLocalObject,User
>
>
> 同时,我修改Student和Teacher bean
> Home接口中的各方法的返回值类型,统一为User
> public User create(String sysid) throws
> CreateException;
> public User findByPrimary(String id);
> ==========================
> session bean :StudentController中的方法:
> ==========================
> public User getUserById(String _sId) throws
> FinderException {
> Context cxt = new InitialContext("Student");
> Object o = cxt.lookup("Student");
> StudentHome stuHome = (StudentHome) o ;
> return stuHome.findByPrimary(_sId);

这一句返回student吧?不是user,所以出错!

> }

我怎么发现你们写代码不喜欢用注释呀??郁闷ing....