EJB3.0这个技术很好用,我们可以把很多的问题都交给EJB3.0的bean容器来管理我们的问题。比如说事务,实体等我们都可以交给容器来管理。这样我们即使用过EJB3.0但是我们对于一些问题,可能就一知半解了。


问题一:当我们抛出一个异常的时候我们的部分业务并没有回滚。

在我们的印象中,似乎抛出异常就必然回滚。但是EJB3.0并没有限制这么严格。而是对异常作了区分。一些RuntimeException,默认就是要回滚的。但是如果是一般的Exception的话,就必须在定义的时候对这个异常进行指定。

javax.ejb.ApplicationException(rollback =true)来指定才可以。应该默认的情况这样的异常是false。

这样在系统自定义的异常类中即可提示自己的业务异常信息,也可以对事务进行回滚操作。

问题2:对于EntityManage.flush()方法的认识。

在很多的书上都写明说flush方法是把数据即时反应到DB中去。其实不然,在一个事务结束之前,即使flush了通过回滚,依然可以回滚成功。我的理解是:我们通过EntityManage来操作数据库的更新和查询。如果多个Bean的话其实是会有多个EntityManage来管理,这样如果没有flush的话,其他的EntityManage获取不到当前最新的信息。如果flush之后,EJB3.0通过大家共用的@PersistenceContext这个对象来实现EntityManage的信息共享。也就是说如果你flush了,其他的EntityManage就可以看到你的更新的内容了,即便你没有commit。

问题3:对于事务的认识

在EJB3.0有两种模式来管理事务,一个是BMT(通过Bean本身来管理事务),一个是CMT(交给容器来管理事务)。我们是推荐CMT的。在CMT中他的默认的方式就是以方法为基础,来实现对事物的控制。默认的情况下方法就是TransactionAttributeTyep.Required的。就是执行一个方法都必须在事务里面。当然还有很多的类型可以选择。比如support 和not support。new 之类的。

讲到这里,问题就来了。当一个方法中调用另外一个方法的时候,如果两个方法的事务控制的要求不一样的时候,怎么处理的。一种情况就是可以协调的,比如说在一个required的方法中调用了New类型的方法的话,当前事务会被挂起,等下面这个方法的事务结束的时候,这个事务才会被继续也就是说,当前的事务失败的时候也没有办法回滚new那个方法中的内容。所以我们在调用其他的方法的时候一定要确定一下调用的方法的事务类型是不是我们需要的。第二种情况就是排斥的情况,required的事务方法中调用了not support的方法的话,那么会抛出异常。