日期:2014-05-19  浏览次数:20850 次

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?;

?<