`

J2EE持久层持久化上下文传播总结(续)

阅读更多

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

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

 

接着上篇“J2EE事务并发控制策略总结”,今天我接着写一下持久化上下文的传播问题。

目前持久层框架都有一个持久化上下文的概念,下面以比较流行的hibernate以及JPA来做一总结。

     如果我们采用OO的方式开发系统,那么势必为了减低耦合,增加内聚,我们会通过细粒度的类来实现业务功能,那么这样就产生了一个问题,如何将持久化上下文在不同的类(这里面其实就是Dao类或者DDD里面的repository)中传播,比如传统的开发方式中,一个service里通过不同的Dao来访问数据库,那么怎么保证不同的Dao类中用的session以及以及与session对应的持久化上下文是同一个呢?这就涉及到了持久化上下文如何传播的问题。下面以我熟悉的hibernate以及JPA来来说明一下,在hibernate中,根据采用的底层事务的不同,需要采用不同的策略来实现:

1 Hibernate中持久化上下文的传播

1.1 采用jdbc事务

此时hibernate通过Threadlocal将当前的session与当前的线程绑定在一起,这样以来只要是同一个线程中的调用,那么获得的session都是同一个,具体来说就是配置hibernate.current_session_context_class属性为thread,这样以来hibernate内部就会通过CurrentSessionContext接口的实现类ThreadlocalSessionContext通过threadlocal来将session和当前线程绑定在一起。当调用SessionFactory的getCurrentSession()方法,返回的就是与当前线程绑定的session,从而解决了持久层上下文传播的问题。

1.2 采用JTA事务

此时hibernate内部是将当前的session以及对应的持久化上下文绑定到了全局的JTA事务上,这样以来我们通过sessionFactory的getCurrentSession()方法获得的就是与当前的JTA事务绑定的session.具体一点就是配置属性hibernate.current_session_context_class为jta,这样以来hibernate内部就是通过CurrentSessionContext接口的实现类JTASessionContext来将session与当前的JTA全局事务绑定在一起,因此当我们通过sf.getCurrentSessionContext()来获取session时,获得的就是与当前的JTA绑定到一起的session.

但是在此种情况下,需要特别注意一个问题:不能同时使用hibernate的Transaction接口与getCurrentSession(),因为当前的session是绑定到全局JTA事务中的,如果通过session.beginTransaction()来开始事务,这说明以前没有事务,既然没有事务存在,我们的session又是怎么绑定到全局JTA事务上的呢?所以一定要注意:当使用JTA事务,并且用了getCurrentSession()的方法时,一定不要用hiernate的native transaction 接口。但是我们如果我们用openSession(),那么就可以通过通过hibernate的native Transaction接口来控制JTA事务。

最后还需要弄清楚一点,Hibernate中还有一种绑定持久化上下文的方法,那就是通过设置hibernate.current_session_context_class属性为managed,hiberante内部就是通过CurrentSessionContext接口的实现类ManagedSessionContext来绑定的。在此种情况下主要是为了实现会话,会话在hibernate中的实现在下面介绍。

2 JPA中持久化上下文的传播

JPA中持久化上下文的传播根据采用不同的事务模型而不同,下面分别来说明:

2.1 采用resource-local事务模型

如果采用resource-local事务模型,此种情况也就是在非J2EE应用服务器的支持下使用。那么我们的持久化上下文的生命周期是与当前的EntityManager绑定到一起的,所以我们可以在不同的类中传播相同的EntityManager实例来达到传播事务上下文的传播。

2.2 采用JTA事务模型

在此种模型下面,我们有EJB容器的支持,持久化上下文的传播是借助于事务上下文来传播的,在说明如何传播前首先要明确EJB组件中两种不同的事务上下文的生命周期:

对于stateless session bean,持久化上下文的生命周期是与当前的系统事务一致的,这也就是无状态会话bean的事务型的持久化上下文,每当事务结束,持久化上下文也就结束了,所有持久化对象也就变为了脱管的(detached).

对于statefull session bean,持久化上下文的生命周期是与当前的有状态会话bean一致的,只有当有状态的会话bean从系统中移除的时候,持久化上下文才关闭,这也就是有状态会话bean的扩展的事务上下文。

搞清楚了这两种不同的事务上下文的生命周期以后,我们来说一下持久化上下文如何传播的问题。持久化上下文是通过当前系统事务来传播的,当一个EJB组件调用另一个EJB组件的时候,如果两个EJB组件的事务范围是一样的,那么持久化上下文就会传播,下面分几种情况来说明:

无状态会话bean之间调用:此时如果两个无状态会话bean在同一个事务中调用,那么持久化上下文就是同一个,通过当前事务来传播。

有状态会话bean调用无状态会话bean:此种情况下如果两者在同一个事务中,那么有状态会话bean的扩展的事务上下文会传播到无状态会话bean里,其实还是通过事务来传播。但是如果被调用的无状态会话bean不支持事务的话(事务属性设置为not support 或者never),那么此时持久化上下文不能传播(JPA规范规定扩展的持久化上下文是不能传播到无事务的stateless session bean)。

有状态会话bean之间调用:此时无论两个有状态会话bean是否支持事务,那么扩展的持久化上下文都会传播,此时就不是通过系统事务来传播的,而是通过statefull session bean的实例来传播(但是此时一定要注意有状态会话bean必须是通过容器注入的或者显示通过JNDI查找)。

    无状态的会话bean调用有状态会话bean:一个有事务范围的持久化上下文的stateless session bean调用一个statefull session bean会引发一个错误,因为当前的事务上下文不能传播)

综上所述,EJB之间的持久化上下文传播是通过我们的系统事务来传播的,如果EJB不支持事务(事务属性设置为not support或者never)),那么持久化上下文就不会传播,但是对于扩展的持久化上下文,是通过statefull session bean来传播的,即使没有事务也可以传播,下篇的如何实现会话会再谈到这个问题。<!---->

前面说的是关于持久化如何在持久层的不同的类之间传播的问题,其实无外乎就是通过当前的线程和当前的系统事务来传播,不过对与statefull session bean的扩展的持久化上下文,传播是通过实例来传播的,在下面的实现会话的讨论中,我还会说到这个问题。当我们掌握了原理的时候,遇到一些问题的时候,我们就会很快找到解决方案。

 

未完待续。。。

下篇“J2EE持久层如何实现会话”

19
2
分享到:
评论
2 楼 SSailYang 2009-01-21  
JBoss Seam 的最初想法就来源于如何在有"conversation"场景的 Web 应用中解决好 Persistence Context 的传播问题
1 楼 lkjust08 2008-12-18  
LZ分析较详细,受教 了

相关推荐

    J2EE Design Patterns

    中文译名:J2EE设计模式 作者: (美)William Crawford & Jonathan Kaplan &lt;br/&gt;本书一边在持久化和消息通信等领域中描述一些新模式,一边向你说明如何在J2EE应用的上下文中实现许多模式。有助于考虑问题...

    J2EE应用开发详解

    50 4.2 开发和部署一个简单的Servlet 51 4.3 Servlet常用API介绍 53 4.3.1 Servlet实现相关 54 4.3.2 Servlet配置相关 54 4.3.3 Servlet异常相关 55 4.3.4 请求和响应相关 55 4.3.5 会话跟踪 56 4.3.6 Servlet上下文 ...

    计算机软件项目设计方案(2020).docx

    技术实现事务管理、服务日志、统一异常处理,在远程服务调用中使用RPC Context实现上下文管理,持久化框架采用Hibernate、Mybatis双框架兼容设计,使用数据访问代理服务,实现分库分表环境下的透明数据访问。...

    java 面试题 总结

    对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。 对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的...

    Spring面试题

    ☆ Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域...

    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 添加一...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    10.3.1 持久化上下文和持久化单元 382 10.3.2 实体类的要求 382 10.3.3 实体的状态 383 10.3.4 管理实体的方法 384 10.4 实体的基本映射387 10.4.1 映射实体类的属性 387 10.4.2 将实体映射到多个表 394 10.4.3 映射...

    java面试题

    Hibernate持久化:Hibernate根据定义的映射规则将对象持久化保存到数据库,这就实现了对象的持久化。 Spring由那几个模块组成? 答:Spring主要由7个模块组成: 1:Spring核心容器:提供了Spring框架的基本功能 2...

    【JeeSpringCloud v3.2.4】后台权限管理系统+互联网云快速开发框架+微服务分布式代码生成

    代码生成前端界面、底层代码(spring mvc、mybatis、Spring boot、Spring Cloud、微服务的生成)、安全框架、视图框架、服务端验证、任务调度、持久层框架、数据库连接池、缓存框架、日志管理、IM等核心技术。...

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

     对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。  对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序...

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

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

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

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

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

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    java源码包---java 源码 大量 实例

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    java源码包2

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    java源码包3

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    java源码包4

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    5个目标文件,演示Address EJB的实现,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...

Global site tag (gtag.js) - Google Analytics