画蛇添足-记spring3 hibernate4整合时遇到问题的处理办法

最近在来到一个新公司,使用新的spring3,hibernate4框架,在使用注解事务总是不起作用。

首先看配置文件,然后再讲解。

首先是springmvc-servlet.xml,这个配置文件是servlet的加载文件,

引用这个文件的位置是在web.xml里

    <!-- 定义 springmvcServlet -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!-- 默认/WEB-INF/[servlet名字]-servlet.xml加载上下文,
                如果配置了contextConfigLocation参数,
                将使用classpath:/springmvc-servlet.xml加载上下文
            -->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/springmvc-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- 拦截匹配的请求,这里所有请求采用名字为mvc-dispatcher的DispatcherServlet处理 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!-- 启动自动扫描该包下所有的Bean(例如@Controller)  这块很重要,会影响到事务-->
    <context:component-scan base-package="com.bpz.demo" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:include-filter>
    </context:component-scan>

    <!-- 定义视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

然后是applicationcontext.xml

<!-- 启动自动扫描该包下所有的Bean  注意这块,也非常重要 -->
    <context:component-scan base-package="com.bpz.demo" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"></context:include-filter>
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"></context:include-filter>
    </context:component-scan>
    <!-- Hibernate4 -->
    <!-- 加载资源文件  其中包含变量信息,必须在Spring配置文件的最前面加载,即第一个加载-->
    <context:property-placeholder location="classpath:mysql.properties" />

    <bean id="sessionFactory"
          class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan">
            <list>
                <!-- 可以加多个包 -->
                <value>com.bpz.demo.entity</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            </props>
        </property>
    </bean>

    <!-- 数据库映射 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.user}" />
        <property name="password" value="${jdbc.pass}" />
    </bean>
    <!-- 基于注释的事务,当注释中发现@Transactional时,使用id为“transactionManager”的事务管理器  -->
    <!-- 如果没有设置transaction-manager的值,则spring以缺省默认的事务管理器来处理事务,默认事务管理器为第一个加载的事务管理器 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!-- 配置Hibernate事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

引用位置是在web.xml里的

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/applicationcontext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

以上是一个正确的配置方式,事务起作用完全没有问题。现在说说为什么很多时候配置的事务未起作用呢。

1.如果事务未起作用还未报错或异常,那应该是使用了sessionFactory.openSession(),在hibernate4里,如果使用spring来管理事务,需要使用

Session session = sessionFactory.getCurrentSession();来获取session。

2.如果使用了Session session = sessionFactory.getCurrentSession();来获取session有可能会报一个异常:

No Session found for current thread

为什么会出现这种情况呢,这和上面的配置就有关系了。一般情况下很多人为了省事,在servlet配置文件里直接

<context:component-scan base-package="com.bpz.demo">
</context:component-scan>

这样配置,对全部代码扫描,但是在servlet里并没有配置事务,所以事务完全不起作用.

不起作用的原因,在另一篇转载的文章里可以看到。

web.xml 中的listener、 filter、servlet 加载顺序及其详解

servlet是最后加载的,在最后使用

context:component-scan

扫描的时候,也会发现在有@Service,@Reposity等注解并进行实例化,由于在servlet配置文件里未配置事务,所以造成了事务不起作用,

看下面的源代码:

    public Session currentSession() throws HibernateException {
        Object value = TransactionSynchronizationManager.getResource(this.sessionFactory);
        if(value instanceof Session) {
            return (Session)value;
        } else if(value instanceof SessionHolder) {
            SessionHolder session2 = (SessionHolder)value;
            Session session1 = session2.getSession();
            if(TransactionSynchronizationManager.isSynchronizationActive() && !session2.isSynchronizedWithTransaction()) {
                TransactionSynchronizationManager.registerSynchronization(new SpringSessionSynchronization(session2, this.sessionFactory));
                session2.setSynchronizedWithTransaction(true);
                FlushMode flushMode = session1.getFlushMode();
                if(flushMode.equals(FlushMode.MANUAL) && !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
                    session1.setFlushMode(FlushMode.AUTO);
                    session2.setPreviousFlushMode(flushMode);
                }
            }

            return session1;
        } else if(this.jtaSessionContext != null) {
            Session session = this.jtaSessionContext.currentSession();
            if(TransactionSynchronizationManager.isSynchronizationActive()) {
                TransactionSynchronizationManager.registerSynchronization(new SpringFlushSynchronization(session));
            }

            return session;
        } else {
            throw new HibernateException("No Session found for current thread");
        }
    }

1:@Transactional声明的方法执行时,Spring的TransactionManager会自动Open Session,自动开启事务,并且将此Sesion绑定到SpringSessionContext(实际上是TransactionSynchronizationManager的ThreadLocal的Map)中..而@Transactional的声明只有

tx:annotation-driven配置才会处理这个声明

2:SessionFactory.getCurrentSession()方法执行时,调用SpringSessionContext.currentSession()从TransactionSynchronizationManager的上下文中查找 当前的Session

3:找到后返回当前的Session,找不到,则返回HibernateException("No Session found for current thread")

对上面源代码的理解。

so:处理事务不起作用的办法就是servlet里做好自己的事,扫描@controller就可以了,这不但能加快启动速度,而且最主要的就是不会  画蛇添足。

				
时间: 2024-10-17 18:45:28

画蛇添足-记spring3 hibernate4整合时遇到问题的处理办法的相关文章

Struts2,Spring3,Hibernate4整合--SSH框架

Struts2,Spring3,Hibernate4整合--SSH框架(学习中) 一.包的导入 1.Spring包 2.Hibernate 包 3.struts 包 4.数据库方面的包及junt4的包 二.配置文件 1.beans.xml (具体要注意的已经注释到 xml 中了,目前整合了Spring 与 hibernate4 ) <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="h

使用Maven搭建Struts2+Spring3+Hibernate4的整合开发环境

做了三年多的JavaEE开发了,在平时的JavaEE开发中,为了能够用最快的速度开发项目,一般都会选择使用Struts2,SpringMVC,Spring,Hibernate,MyBatis这些开源框架来开发项目,而这些框架一般不是单独使用的,经常是Struts2+Spring3+Hibernate.SpringMVC+Spring+Hibernate.SpringMVC+Spring+Mybatis这几种组合中的一种,也就是多个框架配合起来使用.今天来总结一下如何使用Maven搭建Struts

hibernate4整合spring3事务问题

本文是作者在对hibernate4+spring3+struts2整合中遇到的一个问题.对s2sh进行了基本的整合搭建以后,就是对事务的控制管理,将hibernate的事务交由spring管理.根据网上资料,applicationContext.xml中基本的配置如下(注意先后顺序的问题): [html] view plain copy <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&quo

hibernate4整合spring3.1的过程中的异常问题

(1)hibernate4整合spring3.1的过程中,发现了java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider异常 查了一下相关资料,原来发现hibernate4已经将hibernate3的一些功能改掉了,在hibernate4已经不使用CacheProvider了,所以做了以下修改, 原先:<bean id="sessionFactory" class="org.springfram

[转]Struts2+Spring3+Hibernate4+Maven+EasyUI整合入门视频+视频教程源码

[转]Struts2+Spring3+Hibernate4+Maven+EasyUI整合入门视频+视频教程源码 点此立即下载 文件列表:视频教程源码Struts2+Spring3+Hibernate4+Maven+EasyUI整合入门视频008.avi下载地址:https://pan.baidu.com/s/1dcMxMq5xAriJONEpyA06pw Struts2+Spring3+Hibernate4+Maven+EasyUI整合入门视频005.avi Struts2+Spring3+Hi

Struts2+Spring3+Hibernate——整合byMaven

在平时的JavaEE开发中,为了能够用最快的速度开发项目,一般都会选择使用Struts2,SpringMVC,Spring,Hibernate,MyBatis这些开源框架来开发项目,而这些框架一般不是单独使用的,经常是Struts2+Spring3+Hibernate.SpringMVC+Spring+Hibernate.SpringMVC+Spring+Mybatis这几种组合中的一种,也就是多个框架配合起来使用.今天来总结一下如何使用Maven搭建Struts2+Spring3+Hibern

Maven搭建Struts2+Spring3+Hibernate4框架

做了三年多的JavaEE开发了,在平时的JavaEE开发中,为了能够用最快的速度开发项目,一般都会选择使用Struts2,SpringMVC,Spring,Hibernate,MyBatis这些开源框架来开发项目,而这些框架一般不是单独使用的,经常是Struts2+Spring3+Hibernate.SpringMVC+Spring+Hibernate.SpringMVC+Spring+Mybatis这几种组合中的一种,也就是多个框架配合起来使用.今天来总结一下如何使用Maven搭建Struts

mybatis和spring3.1整合

因spring3发布时mybatis还没有出正式版本,所以spring没有整合最新的mybatis.不过社区倒是开发了一个中间件. 需要的jar包 mybatis-3.0.6.jar mybatis-spring-1.0.2.jar 要点: 1.在spring中配置mybatis工厂类 2.在dao层使用spring注入的的工具bean对数据进行操作 整合时,可以有四种方式来使用mybatis进行数据处理. spring 中必须的配置. spring的配置文件中加入以下内容 Xml代码   <!

SpringMVC+Spring3+hibernate4 开发环境搭建以及一个开发实例教程

刚刚接触了SpringMVC这个框架,因此有必要把它拿过来同hibernate.Spring框架进行集成和开发一个实例,在真正企业从头开发的项目中往往一个稳定的开发环境至关重要,开发一个项目选择什么样的搭建平台也需要有经验才可以,并不是说你会搭建一个开发平台然后公司就会用你搭建的开发平台,一个项目或者一个公司看中的也不是你可以搭出框架,而是在这个框架使用过程中出现的各种问题你可以解决掉. 也就是说呢,无论开发什么项目要做到稳定.环境稳定.开发成本稳定.技术稳定.换句话说就是"风险可控"