您的位置:首页 > 编程语言 > Java开发

【JavaEE】经典JAVA EE企业应用实战-读书笔记10

2017-01-19 20:56 429 查看
开发有状态的Session Bean
和无状态的Session Bean并无太大的区别,对开发者来讲,只有如下区别:
1)如果使用Annotation来配置EJB的部署,则将@Stateless改为@Stateful即可。
2)如果使用XML部署描述文件来配置EJB的部署描述信息,则将<session-type>元素的值改为Stateful即可。
对于有状态的Session Bean而言,客户端不要每次都用lookup方法去获取Session
Bean,因为每次调用都会获取一个新的Session Bean,新的Session Bean将无法维护客户端的会话状态。
正确的用法是将Session Bean放入HTTP Session中,保证多个页面中使用的是同一个Session
Bean。
 
对大部分EJB服务器来说,都会通过一个EJB池来维护无状态的Session
Bean,在该EJB池中持有多个无状态Session Bean的实例,这些实例都处于待命状态,准备被客户端调用。
一个无状态的Session Bean从诞生到消亡大致要经历如下的过程。
1)EJB容器开始创建无状态Session Bean的实例。
2)EJB容器对EJB实例执行依赖注入
3)EJB容器滴啊用EJB内以@PostConstruct修饰的生命周期方法。
4)EJB进入待命状态
5)EJB容器调用EJB内以@PreDestroy修饰的生命周期方法
6)EJB实例被垃圾回收
无状态Session Bean有3个状态:不存在状态、待命状态和被销毁状态。
 


有状态的Session Bean比无状态的Session Bean多了一个去活状态,多了两个Annotation。@PrePassive和@PostActivate。
@PostConstruct:修饰的方法会在EJB创建之后被EJB容器调用。
@PreDestroy:修饰的方法会在EJB被销毁之前被EJB容器调用。
@PostActivate:修饰的方法将会在有状态的Session Bean从去活状态恢复出来之后被EJB容器调用,该方法执行完成之后该EJB再次进入待命状态。
@PrePassivate:修饰的方法将会在有状态的Session Bean去活之前被EJB容器调用。
@Remove:修饰的方法实际上应该属于一个业务方法,用于被客户端调用,当客户端调用某个有状态Session Bean的@Remove修饰的方法之后,相当于客户端通知服务器应该删除该有状态的Session
Bean。因此EJB容器会立即调用该Session Bean的@PreDestroy修饰的方法,然后销毁该Session
Bean。
 
在基于EJB的JavaEE中,Session Bean从功能上大致分为两类。
1)用于封装底层的实体和JPA,用于访问底层的实体,可称为EAO(Entity Access
Object)对象,本质上的功能就是DAO。
2)充当业务组件,底层EAO对象的Facade(门面),系统控制器(比如Struts的Action、JSF的托管Bean等)将调用他们的业务方法来处理用户的请求。
第一类Bean不需要事务控制,第二类的每个业务方法用于处理一次用户请求,代表一次完整的业务逻辑,需要添加事务控制。
CMT的事务边界总是以方法的开始、结束作为边界的。
使用@TransactionManagement时通过其value属性指定使用CMT还是BMT。
其value属性值只能有如下两个:
TransactionManagementType.BEAN:指定使用BMT
TransactionManagementType.CONTAINER:指定使用CMT
使用<transaction-type>时也只能接收两个值:Bean和Container
 
开发者使用CMT,则应该使用@TransactionAttribut来指定事务属性。
其value属性的值可以是javax.ejb.TransactionAttributeType枚举值之一。
@Remote
public interface Cmt {
void insert();
}
@Stateless(mappedName = "Cmt")
@TransactionManagement(TransactionManagementType.CONTAINER)//重点
@TransactionAttribute(TransactionAttributeType.REQUIRED)//重点
public class CmtBean implements Cmt {
private DataSource ds = null;
@Resource
private SessionContext sessCtx;
public CmtBean() throws NamingException {
Context ctx = new InitialContext();
ds = (DataSource) ctx.lookup("javaee");
}
@Override
public void insert() {
try {
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
int result = stmt.executeUpdate("insert into user values(1,'new','bbb')");
System.out.println(result);
// 下面的语句会报错,主键重复
stmt.execute("insert into user values(1,'new','bbb')");
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
sessCtx.setRollbackOnly();//重点
}
}
}
sessCtx.setRollbackOnly();这条代码用于设置EJB的事务回滚,但是如果其Bean方法执行时引发了其他应用自定义异常,CMT的事务控制将不会让事务回滚。
如果希望调用EJB方法时抛出其他异常也会回滚事务,有两种方式

1)使用EJBContext的setRollbackOnly方法。
2)使用@ApplicationException的注解
第二种方法可以指定一个rollback属性,属性为true则表明执行EJB的业务方法中引发该异常将让事务自动回滚。
由于CMT表示容器会接管EJB业务方法中的事务,因此开发者不应该在EJB业务方法中调用这些方法不限于:
1)java.sql.Connection的setAutoCommit(false)、commit、rollback
2)javax.ejb.EJBContext的getUserTransaction
3)javax.transaction.UserTransaction的任何方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: