CGLIB实现的一个hibernate事务管理代理类出现的问题,以及一些疑问

问题描述

先声明下,本人系菜鸟一个,问的问题如果类似于1+1为什么等于2,请少拍板这2天在学习CGLIB,一时兴起用CGLIB实现了一个管理hibernate事务的类。代码如下:package com.test;import java.lang.reflect.Method;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.Transaction;import com.linbs.core.common.hibernate.HibernateUtil;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;/** * 使用CGLIB进行事务处理设置 * @author linbs */public class TransactionDAOProxy implements MethodInterceptor {private static Log logger = LogFactory.getLog(TransactionDAOProxy.class);private Enhancer enhancer=new Enhancer();public Object getDAO(Class clz){ enhancer.setSuperclass(clz); enhancer.setCallback(this); return enhancer.create(); }public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {Session session = null;Transaction tx = null;Object result = null;try{session = HibernateUtil.getSession();tx = session.beginTransaction();result = proxy.invokeSuper(obj, args);tx.commit();session.flush();}catch(HibernateException e){try {tx.rollback();} catch (HibernateException e1) {logger.error(e1.getMessage());throw e;}}finally{try {HibernateUtil.closeSession();} catch (HibernateException e) {logger.error(e.getMessage());throw new Throwable("关闭session时出错!");}}return result;}}其中的HibernateUtil类的getSession()方法是一个从线程中取得session副本的函数,代码相信各位大牛已经很熟悉,在此就不贴出来了。测试类如下:package com.test;import com.linbs.core.common.hibernate.BaseHibernateDAO;import com.linbs.usermanage.model.User;public class Test {public static void main(String[] args){TransactionDAOProxy proxy = new TransactionDAOProxy();BaseHibernateDAO baseDAO = (BaseHibernateDAO)proxy.getDAO(BaseHibernateDAO.class);User user = new User();user.setUserName("abcProxy");user.setUserPwd("abcProxy");user.setEmail("abc@126.cn");baseDAO.save(user);}}其中的baseDAO.save(user);函数代码如下:/** * 取得当期进程的session对象 * @return */public Session getSession() {return HibernateUtil.getSession();}/** * 保存一个新的实体类的实例,并返回标识号 * @param obj * @return */public Serializable save(final Object obj) {return this.getSession().save(obj);}测试类运行的时候报出了如下错误:Exception in thread "main" org.hibernate.SessionException: Session is closed!at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:49)at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:526)at org.hibernate.impl.SessionImpl.save(SessionImpl.java:518)at org.hibernate.impl.SessionImpl.save(SessionImpl.java:514)at com.linbs.core.common.hibernate.BaseHibernateDAO.save(BaseHibernateDAO.java:31)at com.linbs.core.common.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e.CGLIB$save$3(<generated>)at com.linbs.core.common.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e$$FastClassByCGLIB$$e5947bbb.invoke(<generated>)at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:167)at com.test.TransactionDAOProxy.intercept(TransactionDAOProxy.java:49)at com.linbs.core.common.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e.save(<generated>)at com.test.Test.main(Test.java:21)通过debug发现session = HibernateUtil.getSession();和result = proxy.invokeSuper(obj, args);中调用的session不属于同一个对象。而session是在线程中取得的,可见session = HibernateUtil.getSession();和result = proxy.invokeSuper(obj, args);不是在同一个线程中运行的。于是猜想:cglib在运行中动态创建类而新创建的类和原来创建的类是不在同一线程中运行的,不知道我的猜想是不是正确,请各位大牛指教!!

解决方案

enhancer的原理就是用Enhancer生成一个原有类的子类,并且设置好callback到proxy, 则原有类的每个方法调用都会转为调用实现了MethodInterceptor接口的proxy的intercept() 函数:public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) 你的代码中代理的是BaseHibernateDAO这个类,再调用save的时候,会内部调用到getSession的方法,而这个方法同样也会给拦截。。同样进入intercept,最后还把事务给提交了,再回到调用真的save的时候,就会出现session已经关闭的提示。。。这是我的想法,兄弟你可以再测试测试。

时间: 2024-10-28 05:57:22

CGLIB实现的一个hibernate事务管理代理类出现的问题,以及一些疑问的相关文章

Spring 事务管理高级应用难点剖析: 第 2 部分

本文是"Spring 事务管理高级应用难点剖析" 系列文章的第 2 部分,作者将继续深入剖析在实际 Spring 事务管理应用中容易遇见的一些难点,包括混合使用多种数据访问技术(如 Spring JDBC + Hibernate)的事务管理问题,以及通过 Spring AOP 增强的 Bean 存在的一些比较特殊的情况. 联合军种作战的混乱 Spring 抽象的 DAO 体系兼容多种数据访问技术,它们各有特色,各有千秋.像 Hibernate 是非常优秀的 ORM 实现方案,但对底层

java版云笔记(七)之事务管理

事务管理 事务:程序为了保证业务处理的完整性,执行的一条或多条SQL语句. 事务管理:对事务中的SQL语句进行提交或者回滚. 事物管理对于企业应用来说是至关重要的,好使出现异常情况,它也可以保证数据的一致性,不出现脏数据. Spring Framework对事务管理提供了一致的抽象,其特点如下: 为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Da

Spring 事务管理高级应用难点剖析: 第 1 部分

Spring 的事务管理是被使用得最多的功能之一,虽然 Spring 事务管理已经帮助程序员将要做的事情减到了最小.但在实际开发中,如果使用不当,依然会造成数据连接泄漏等问题.本系列以实际应用中所碰到的各种复杂的场 景为着眼点,对这些应用的难点进行深度的剖析. DAO 和事务管理的牵绊 很少有使用 Spring 但不使用 Spring 事务管理器的应用,因此常常有人会问:是否用了 Spring,就一定要用 Spring 事务管理器,否则就无法进行数据的持久化操作呢?事务管理器和 DAO 是什么关

Spring事务管理--多个ORM框架在使用时的情况分析

   公司的项目已经接近尾声了,总结一下项目中用到的技术,我发现项目中的有些东西还是挺模糊的,只是知道这么用就行了.并不清楚其中的原理.由于公司的项目比较老,是7年前的一个项目了,中间一直有人在维护,也是在这个过程中不断融入了新的东西,比如就项目的持久化这块来说,就用了ibatis.mybatis.hibernate.spring JDBC四种混合的框架.究其原因只能说是历史遗留问题,就不做过多的解释了.但是这么多持久化的框架如何协同工作的,尤其是事务的控制,一个系统中使用如此多的持久化框架是,

WSDL手动生成WebService代理类的方法

通常要手动生成WebService代理类需要把一句生成语句,如 wsdl.exe /l:cs /out:D:\Proxy_UpdateService.cs http://localhost:1101/UpdateService.asmx?wsdl拷贝到Visual Studio 2005 命令提示窗口中去执行,这里再介绍另一个办法. 首先打开Visual Studio 2005,选择菜单"工具"-"外部工具"打开外部工具对话框,如图,单击"添加"

如何使用Hibernate来管理事务

在数据库应用程序中最基本的操作是CRUD(创建/读取/更新/删除),这4个操作构成了数据库应用程序的基石.在单机时代,一个数据库只由一个应用程序使用,这样CRUD操作并不会带来什么负面影响,但当进入网络时代后,这一切都发生了改变.由于网络数据库程序一般是由多个客户端同时操作一个数据库,因此,传统的CRUD操作将变得不再安全.因此,这个问题将引出本文的中心内容:事务.通过事务可以使传统的CRUD操作适应网络数据库应用. 本文分为三个部分.第一部分讨论了Hibernate如何管理事务和会话.第二部分

struts2-spring配置方式管理hibernate事务的情况下,每过一段时间产生的错误

问题描述 spring配置方式管理hibernate事务的情况下,每过一段时间产生的错误 项目的背景是struts2+spring+hibernate3 weblogic服务器集群环境 数据库oracle spring管理hibernate 采用配置的方式,配置在了service层. 数据库连接方面使用了hibernate自带的连接池(用其他第三方连接池也试了,问题依旧) 现象:每过一段时间便会报错:(部分) jdbc rollback failed ... TransactionExcepti

Spirng 4 、Hibernate 4 事务管理

建议将 Hibernate SessionFactory 交给 Spring 进行事务管理,在 applicationContext.xml 里面配置 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <!-- 数据源 --> <property name="dataSource"

Spring与Hibernate整合事务管理的理解_java

在谈Spring事务管理之前我们想一下在我们不用Spring的时候,在Hibernate中我们是怎么进行数据操作的.在Hibernate中我们每次进行一个操作的的时候我们都是要先开启事务,然后进行数据操作,然后提交事务,关闭事务,我们这样做的原因是因为Hibernate默认的事务自动提交是false,他是需要我们人为的手动提交事务,假如你不想每次都手动提交事务的话,你可以在hibernate.cfg.xml我文件中把它设置为事务自动提交: xml代码 <property name="def