`

J2EE持久层会话实现(续)

阅读更多

作者:狂放不羁 
   网址: http://yuquan-nana.iteye.com

    >>>转载请注明出处!<<<
 

 

接着上篇“J2EE持久层持久化上下文传播总结”,这篇文章总结一下如何利用当今J2EE比较流行的持久层框架Hibernate和持久层标准JPA来实现会话。

 

在讨论此问题之前,首先要明确一个问题,什么是会话?会话简单的可以理解为跨多个request生命周期,就拿那个投修改简历的问题来说,第一个事务读取简历,用户修改,然后再通过另外一个事务去更新简历,那么读取和更新是在不同的事务中完成的,那么我们怎么实现这种用例呢?如果采用ORM框架,实现起来会轻松很多,下面就以hibernate和JPA来做一总结。

1. Hibernate实现会话:在hibernate中实现会话可以采用两种策略。

第一种就是采用detached object,在此种情况下,我们只需要用hibernate提供的reattach和merge操作将脱管对象重附或者是合并到当前的持久化上下文,hibernate会为我们检测更新并最后决定同步到数据库。

第二种就是通过ManagedSessionContext来扩展持久化上下文,使其跨越几个request生命周期。在使用ManagedSessionContext来实现扩展持久化上下文时,一定要记得设置session的flushmode为FlushMode.MANUAL.这样在每次事务提交的时候就不会同步持久化上下文。(不幸的是JPA规范中没有此选项,我们只能通过非事务型的操作来实现,但是如果采用EJB模型,那么我们就可以采用statefull session bean默认的扩展的持久化上下文)。

下面我主要说一下如何在JPA中来实现会话:

2. JPA中实现会话:在JPA中实现会话,我主要结合EJB的编程模型来做一总结,因为EJB编程模型为我们做了很多简化,免得我们自己动手实现,但是如果要在非J2EE托管环境下使用JPA,就要自己实现。

第一种策略:采用脱管对象来实现。在这之前首先要明确一个问题,那就是JPA只提供了对脱管对象的merge(合并)操作,没有提供reattach(重附操作),所以我们采用脱管对象实现会话时,在会话的最后一个request生命周期中,我们通过合并来将脱管对象合并到持久化上下文,当然detached object对象,我们一般是保存到httpsession里面,但是这样一个不好的地方就是将业务逻辑泄露到了表现层,不利于层的内聚性,所以我们可以采取EJB编程模型给我们带来的便利方式来实现,通过扩展的持久化上下文来实现,下面就来说说如何通过扩展的持久化上下文来实现会话。

第二种策略:采用statefull session bean扩展的持久化上下文来实现。因为在EJB3.0中,有状态会话bean默认采取扩展的持久化上下(extended persistence context),持久化上下文的生命周期与statefull session bean的生命周期是一致的,所以我们可以通过此扩展的持久化上下文来实现会话。为了更加清楚,我采用以下代码来描述:

@Statefull

@Remote(BussinessInterface.class)

public class ConversationBean implements BusinessInterface{

 

@PersistenceContext(type = PersistenceContextType.EXTENDED)

EntityManager em ;

 

public OperationResult firstOperation(...){

//此方法实现会话的第一个请求

}

 

//省略会话的中间阶段的请求方法,我只用一个来描述

public OperationResult middleOperation(..){

//此方法可以实现会话的一些中间操作,比如查询等

}

 

..........

 

//会话的最后一个请求

public OperationResult lastOperation(...){

 

 

}

 

 

}

但是此种情况下实现会话需要注意一个问题,因为EJB3.0规范没有像hibernate那样的人工刷新持久化上下文的选项,所以此时要想会话的中间阶段不刷新持久化上下文,为了让会话的中间阶段不刷新持久化上下文(同步持久化上下文到数据库),那么或者采用hibernate扩展或者采用非事务型的EJB组件方法调用(因为JPA规范只有两种持久化上下文的刷新模式,一种是AUTO,它是默认的刷新选项,第二种是commit,第一种要求在执行查询和事务提交的时候都刷新持久化上下文)。分两种情况来描述:

采用Hibernate扩展:此种情况下,我们需要增加以下注释:

........

@PersistenceContext(type=PersistenceContextType.EXTENDE,

  propertites = @PersistenceProperty(name="org.hibernate.flushMode",   

  value="MANUAL")

EntityManager em;

 

......

 

以上的注释也可以采用等价的XML部署描述来替换。

通过以上的注释,当我们的客户端调用会话中间操作时,当前与ConversationBean绑定的扩展的持久化上下文就不会刷新(因为默认会在middleOperation()方法调用的时候启动事务,结束后提交事务,而如果按照JPA标准的话,flushMode无论是AUTO,还是COMMIT,都会刷新持久化上下文,并且如果我们在中间操作进行查询操作,也会触发刷新持久化上下文的操作),当然因为当前的持久化上下文是人工刷新的,那么我们就需要在会话的最后一个操作中,本例中,也就是lastOperation中手动刷新数据库,代码如下:

 

public OperationResult lastOperation(...){

 

em.flush();

em.commit();//注意此时em是可选的,因为默认在方法调用后会自动提交事务。

}

此时我们还可以将一个会话通过面向对象的设计来进行分解,比如我们可能还需要其它的EJB来实现会话,那么我们可以将其通过@EJB注释让容器帮我们注入,这样以来不同的EJB之间的传播会通过当前的系统事务来传播持久化上下文(具体请参考上篇持久化上下文传播)

采用目前JPA规范建议方法:非事务型的EJB方法调用。我们可以修改ConversationBean的代码如下:

@Statefull

@Remote(BussinessInterface.class)

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORT)

public class ConversationBean implements BusinessInterface{

 

@PersistenceContext(type = PersistenceContextType.EXTENDED)

EntityManager em ;

 

public OperationResult firstOperation(...){

//此方法实现会话的第一个请求

}

 

//省略会话的中间阶段的请求方法,我只用一个来描述

public OperationResult middleOperation(..){

//此方法可以实现会话的一些中间操作,比如查询等

}

 

..........

 

//会话的最后一个请求

@Remove

@TransactionAttribute(TransactionAttributeType,REQUIRED)

public OperationResult lastOperation(...){

 

   em.flush();

   em.commit();//注意此时em是可选的,因为默认在方法调用后会自动     提交事务。

 

}

}

以上代码改变的地方就是我们将ConversationBean的事务属性改为了not support(默认情况下是REQUIRED),这样以来我们的ConverstationBean的调用就不会在事务中进行,所有的会话操作都会放在一个队列中,当我们的扩展的持久化上下文重新与事务关联的时候,当事务提交时同步到数据库。但是有个问题,如果ConversationBean还会调用的EJB bean怎么办?因为当前的bean不支持事务,那么持久化上下文是不能通过事务来传播的,比如ConversationBean会与另外一个bean进行协作,我们定义如下:

@Stateless

@Remote(AnotherBussinessInterface.class)

public class AssistBean implements AnotherBusinessInterface{

 

.........

}

 

此时我们需要增加如下代码到ConversationBean中:

.......

//通过@EJB注释,EJB容器会将实例池里的一个实例注入到当前的 ConversationBean里。

@EJB

AnotherBusinessInterface assistBean;

........

 

这样以来,我们遇到了持久化上下文传播的问题,因为此时ConversationBean不支持事务,所以扩展的持久化上下文是传播不到没有无状态会话bean里的(这个是JPA规范规定的,不能在没有事务的情况下,传播扩展的持久化上下文到stateless session bean),那么既然持久化上下文不能得到传播,那么我们同一个会话中就会有不同的持久化上下文,这样就不能保证会话的完整性。那么我们有没有办法来采取采取措施补救呢?幸亏还有哈哈,那就是我们可以将AssistBean改为有状态的会话bean,这样以来,因为扩展的持久化上下文此时通过bean实例来传播的,所以不同的有状态会话bean里会采用同一个持久化上下文。所以我们要想通过有状态会话bean的扩展的持久化上下文来实现会话,会话设计到的所有的bean必须都要是statefull,造成这样不方便的原因也就在与当前JPA标准不支持FlushMode.MANUAL,如果JPA也支持了此选项,那么我们通过扩展的持久化上下文实现会话将变得更加容易,希望以后JPA标准能加入FlushMode.MANUAL选项。

综上所述,实现会话我们可以采取两种措施,第一种就是通过detached object,这样的不好地方就是业务状态都保存到了表现层,不利于分层架构,不利于层的内聚性,所以为了将业务状态保存到业务层,那么我们可以采取扩展的持久化上下文,虽然hibernate支持flushModel.MANUAL的选项,但是要自己动手实现扩展的持久化上下文,而EJB提供了扩展的持久化上下文,但是又没有提供FlushMode.MANUAL的选项,所以如果各有个的好处,遗憾的是不能两全其美。但是当采用EJB的扩展的持久化上下文,这样不用自己动手实现,唯一不好的地方就是要么通过hiberante的扩展来关闭事务提交自动刷新持久化上下文,要么通过非事务型的EJB方法调用来关闭事务提交自动刷新持久化上下文,所以如果我们EJB容器采用了Hiberante做为JPA标准的实现,那么我们最好借助与Hiberante的扩展,以及statefull session bean的扩展的持久化上下文来实现会话。

4
0
分享到:
评论

相关推荐

    揭开J2EE集群的面纱 pdf

    4.WEB层集群实现8 4.1.WEB层负载均衡 4.2.HTTP会话的失败转移 4.2.1.数据库持久方案 4.2.2.内存复制方案 4.2.3.Tomcat的方案:多服务器复制 4.2.4.WebLogic, WebSphere, JBoss的方案:结对服务器(Paired servers)...

    J2EE中文版指南 CHM格式 带全文检索

    The J2EE Tutorial 2 目录 3 第一部分 介绍 13 准备工作 13 谁应该使用这指南 13 关于例子 13 理解例子的准备工作 13 例子下载 13 如何编译并运行例子 13 相关信息 14 第1章 总 括 14 一.分布式得多层应用程序 14 ...

    实用J2EE设计模式编程指南

    第2章 Web层设计模式 表示模式 案例:宾馆订房管理系统 标识模式 小结 第3章 持久性框架设计模式 开始模型 何谓持久性框架 TitleDAO会话Bean Value Object模式 Service Locator模式 使用持久性框架 持久性框架...

    J2EE应用开发详解

    内容为J2EE应用开发详解中的源代码 第1章 Java Web应用开发简介 1 1.1 Java EE应用概述 1 1.2 Java EE概念 1 1.2.1 Java EE多层模型 1 1.2.2 Java EE体系结构 2 1.3 Java EE的核心API与组件 4 1.4 Web服务器和应用...

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    由于J2EE的开源的框架中提供了MVC模式实现框架Struts、对象关系模型中的Hibernate 的框架及拥有事务管理和依赖注入的Spring。利用现存框架可以更快开发系统。所以选择Java技术作为blog 的开发工具。 为了增加系统的...

    J2EE企业级开源框架bboss v5.0.6.8

    bboss功能涵盖ioc,mvc,jsp自定义标签库,持久层,全局事务托管,安全认证,SSO,web会话共享,cxfwebservice服务发布和管理,hessian服务发布和管理等功能。另外还提供了符合中国式自由流的bboss activiti工作流...

    J2EE企业级开源框架bboss源代码

    bboss是一个j2ee开源框架,为企业级应用开发提供一站...bboss功能涵盖ioc,mvc,jsp自定义标签库,持久层,全局事务托管,安全认证,SSO,web会话共享,cxfwebservice服务发布和管理,hessian服务发布和管理等功能。另

    J2EE企业级开源框架bboss v5.0

    bboss是一个j2ee开源框架,为企业级应用开发提供一站...bboss功能涵盖ioc,mvc,jsp自定义标签库,持久层,全局事务托管,安全认证,SSO,web会话共享,cxfwebservice服务发布和管理,hessian服务发布和管理等功能。另

    java 面试题 总结

    但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地...

    spring in action英文版

     1.6.4 持久层框架  1.7 小结  第2章 装配Bean  2.1 容纳你的Bean  2.1.1 BeanFactory介绍  2.1.2 使用应用上下文  2.1.3 Bean的生命  2.2 基本装配  2.2.1 使用XML装配  2.2.2 添加一...

    iBase4J分布式系统-其他

    核心框架:Sring boot + Spring Framework + Dubbo + ibase4j-common安全框架:Apache Shiro任务调度:Spring + Quartz持久层框架:MyBatis + MyBatis-Plus数据库连接池:Alibaba Druid缓存框架:Redis会话管理:...

    超级有影响力霸气的Java面试题大全文档

    但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地...

    Java数据库编程宝典2

    4.2 两层和三层模型 4.2.1 两层模型 4.2.2 三层模型 4.3 SQL的一致性 4.4 JDBC兼容性 4.5 JDBC如何工作 4.5.1 DriverManager 4.5.2 JDBC DataSource 4.5.3 DataSource对象和JNDI 4.5.4 部署和使用...

    Java数据库编程宝典4

    4.2 两层和三层模型 4.2.1 两层模型 4.2.2 三层模型 4.3 SQL的一致性 4.4 JDBC兼容性 4.5 JDBC如何工作 4.5.1 DriverManager 4.5.2 JDBC DataSource 4.5.3 DataSource对象和JNDI 4.5.4 部署和使用...

    Java数据库编程宝典1

    4.2 两层和三层模型 4.2.1 两层模型 4.2.2 三层模型 4.3 SQL的一致性 4.4 JDBC兼容性 4.5 JDBC如何工作 4.5.1 DriverManager 4.5.2 JDBC DataSource 4.5.3 DataSource对象和JNDI 4.5.4 部署和使用...

    Java数据库编程宝典3

    4.2 两层和三层模型 4.2.1 两层模型 4.2.2 三层模型 4.3 SQL的一致性 4.4 JDBC兼容性 4.5 JDBC如何工作 4.5.1 DriverManager 4.5.2 JDBC DataSource 4.5.3 DataSource对象和JNDI 4.5.4 部署和使用...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    其中使用Struts作为系统的整体基础架构,负责MVC的分离,在Struts框架的模型部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring做管理,管理Struts和Hibernate。 WebStorage HTML新增的本地存储解决...

    JAVA上百实例源码以及开源项目

    两个例子,无状态SessionBean可会话Bean必须实现SessionBean,获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,计算利息等;在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将...

    JAVA上百实例源码以及开源项目源代码

    Java EJB中有、无状态SessionBean的两个例子 两个例子,无状态SessionBean可会话Bean必须实现SessionBean,获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,计算利息等;在有状态SessionBean中,用...

Global site tag (gtag.js) - Google Analytics