EJB事务问题请高手赐教2

try{
Section section = sectionHome.create(id,name,depth,type);
section.setParent(sectionHome.findByPrimaryKey(parentId));
System.out.println("对象已经创建");
}catch(Exception e){
System.out.println(e.getMessage());
}

sectionHome.create(id,name,depth,type);方法成功执行后
sectionHome.findByPrimaryKey(parentId)方法发生finder异常
但是我发现数据库已经发生变化,没有把第一句的操作进行回滚,下边是我的
ejb-jar文件的一段内容内容,看看我的required用的正确吗(声明我用的是jboss服务器,是不是和数据源配置有关系)



<container-transaction>
<method>
<ejb-name>SectionService</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>Section</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>


是否使用Oracle-XA.xml这样配置文件?

你要知道事务是从什么时候开始的。

1 假设调用者并没有启动事务,则Container根据sectionService的"required",启动一个事务t,sectionService调用EntityBean的时候会将t传给EntityBean(通常EntityBean也为Required)。

在这种情况下,事务从调用sectionService方法起始,要等sectionService方法退出后才会回滚。

2 假设调用者已经启动事务x了,则Container根据sectionService的"required",将x传给sectionService,当然也会传给EntityBean。

在这种情况下,事务从调用者方法起始,即使sectionService方法退出,也不能回滚,要返回到启动事务的那个点,才回滚。

===============

另外,XA是不需要的,如果你只有一个数据源的话。如果你有多个数据库参与一个事务,则每个数据库都要支持XA。

感谢楼上的高手们
下面是上面代码的完整函数


public void createSection(String id, String name, String parentId, String type, String depth) {
try{
Section section = sectionHome.create(id,name,depth,type);
section.setParent(sectionHome.findByPrimaryKey(parentId));
System.out.println("对象已经创建");
}catch(Exception e){
System.out.println(e.getMessage());
}
}

createSection这个方法是session bean 中的,并且是在servlet中被调用的,在调用这个方法时ejb服务应该启动了一个事务,而这个方法体内的操作也应该是加入了这个事务之中的,但是运行结果就是以前我说的那样。不知道我这么分析对吗?还请高手指点。

仔细看看j2ee tutorial吧:

There are two ways to roll back a container-managed transaction. First, if a system exception is thrown, the container will automatically roll back the transaction. Second, by invoking the setRollbackOnly method of the EJBContext interface, the bean method instructs the container to roll back the transaction.


因此有三种方法:
1。sessionBean不要Catch findXXX()调用扔出来的系统Exception,


public void createSection(String id, String name, String parentId, String type, String depth) {

Section section = sectionHome.create(id,name,depth,type);
section.setParent(sectionHome.findByPrimaryKey(parentId));
}

2。你Catch findXXX() Exception后再扔EJBException


public void createSection(String id, String name, String parentId, String type, String depth) {
try{ Section section = sectionHome.create(id,name,depth,type);
section.setParent(sectionHome.findByPrimaryKey(parentId));
System.out.println("对象已经创建");
}catch(Exception e){
System.out.println(e.getMessage());
throw e;
}
}

3。调用EJBContext.setRollbackOnly()


public void createSection(String id, String name, String parentId, String type, String depth) {
try{
Section section = sectionHome.create(id,name,depth,type);
section.setParent(sectionHome.findByPrimaryKey(parentId));
System.out.println("对象已经创建");
}catch(Exception e){
System.out.println(e.getMessage());
ctx.setRollbackOnly(true);}
}

第一种办法最简单明了;如果要跟踪错误用第二种;第三种不推荐。


就是这个原因,范了一个低级错误,不应该在方法体内捕获这个异常的。谢谢楼上的兄弟。