1、Dao:用于封装底层的实体和JPA,访问实体,可称为EAO对象(Entity Access Object) ,本质上就是三层中Dao层。
2、Service:主要用于业务层,调用Dao层方法,实现主要的业务逻辑编写。
Session Bean用于Dao层eao对象时,通常不需要事务控制,但作为业务逻辑处理用户请求,代表一次完整的业务逻辑,通常都需要添加事务控制。
EJB提供了两种事务管理方式:
1、容器事务管理(CMT)
容器管理事务主要是通过容器自动控制事务的开启,提交和回滚,开发人员不需要手工编写代码,由容器来控制事务的边界,一般来说是业务方法的开始是事务的开启,业务方法的结束是事务的提交部分,当程序遇到运行时异常,事务会自动回滚。
Spring容器内置的AOP机制即声明式事务管理,只需要在spring容器中配置简单,即可为业务Bean增加事务支持。这大家应该都不会陌生,在项目中也多次使用到spring事务管理,这就是CMT的应用。开发人员无需在代码中进行事务控制。EJB同样也具备该属性。
2、Bean 事务管理( BMT )
BMT主要是通过手工编程来实现事务的开启、提交和回滚,相对于CMT来说虽然增加了工作量,但是控制力度更细,而且更加灵活,我们可以再出现异常的时候回滚事务也可以通过JMS返回或者远程调用返回值来控制事务的回滚或提交。
Session Bean实现事务控制和消息Bean是完全一样的,都是通过在Bean上使用@TransactionManagement和@TransactionAttribute来控制。和Spring 类似,EJB除了使用注解,同样也可通过配置文件配置对业务Bean 进行事务管理。
1、确定事务管理类型
为Session Bean的方法指定事务类型可通过@TransactionManagement()注解或者<transaction-type>确定。
1)指定使用CMT事务管理:
@TransactionManagement(TransactionManagementType.CONTAINER)
2)指定使用BMT事务管理:
@TransactionManagement(TransactionManagementType.BEAN)
2、事务传播属性
由于方法调用的原因,比如方法 A 调用方法 B 的时候。如果方法 A 在事务环境中运行,那么方法 B 是否也要在事务中运行呢,方法 B 是要和方法 A 在同一个事务中运行还是新开起一个事物呢?等等。要弄清楚这些问题,就要牵涉到事务传播属性的配置,EJB 中针对不同的的情况提供了下面六种不同的事物传播属性:
通过@TtransactionAattribute()设置事务传播属性。
@TransactionAttribute(TransactionAttributeType.REQUIRED)
TransactionAttributeType是一个枚举类型:
<span style="font-size:12px;">public enum TransactionAttributeType { REQUIRED, REQUIRES_NEW, SUPPORTS, NOTSUPPORTED, MANDATORY, NEVER }</span>
Required:用该属性标注的方法或组件总是在事务中运行。如果客户端已经在事务中,则在原事务中运行;如果没有事务,则开启一个新事务,在其中运行。
Requires_New:方法或组件总是在新开启的事务中运行。如果客户端已经在事务中,则首先将原事务挂起,然后新开启一个事务,在其中运行,新事务结束之后,原来事务从挂起点继续执行;如果没有事务,则开启一个新事务,在其中运行。
Supports:和 Required 属性的不同点是,在没有事务的环境中不会开启一个新事务;如果存在事务的话则加入其中运行,这点和 Reuqired 相同。
Not_Supported:如果事务已经存在的情况下,则原来的事务要挂起,然后调用标注该属性的方法或组件,调用结束之后,继续原来的事务;无事务环境中调用的时候,不开启新事务,这点和 Supports 相同。
Mandatory:调用标注该属性的方法或组件的客户端,必须已经在事务中,如果不在事务中则会抛出异常;如果已经在事务中,则加入原来事务运行。和 Required 不同的是,该属性不会自动开启新的事务;
Never:用 Never 属性标注的方法或组件,不能在事务中运行。如果调用该方法或组件的客户端已经在事务中,则抛出异常。
在ITOO中EJB事务控制也发挥着重要作用,通EJB在业务层使用事务控制的原则一致,ITOO中使用EJB事务控制主要在业务实现层,通过注解配置事务管理方式和事务传播属性,大多使用容器事务和required 属性进行配置。例如以下代码:
@Stateless(name = "studentBeanImpl") //设置该Bean为无状态Bean @Remote(StudentBean.class) //在实现类中设置该Bean为远程调用Bean,接口为StudentBean @TransactionManagement(TransactionManagementType.CONTAINER) //设置事务管理类型为容器事务管理 @TransactionAttribute(TransactionAttributeType.REQUIRED) //事务传播属性为required public class StudentBeanImpl extends BaseBeanImpl<Student> implements StudentBean { ....................... }