Spring+Hibernate事务管理

来源:互联网 发布:游戏音效增强软件 编辑:程序博客网 时间:2024/06/06 12:31

一 前言

       近期在项目开发中,遇到了spring+hibernate开发的问题,在程序启动的过程中,出现了hibernate无法获取会话,事务无法创建的情况。追踪问题,并查文章,资料之后,发现有段程序写的有问题。另,对hibernate事务管理,springhibernate事务管理有了更深一层认识。下面说下个人见解和总结,希望有所裨益。


二 原理

                     getSession:

                                hibernate在事务管理中通过getseesion()获取会话,不能自动关闭,所以如果多线程,高并发访问的话,会话未关闭,会严重占用数据库资源。

                      getCurrentSession:

                                  spring与hibernate集成后通过TransactionSynchronizationManager下的sessionholder来产生并返回session,有hibernateDaoSupport来释放资源

                       openSession:

                               有hibernateTemplate产生session,但是不会绑定到线程,需要显示关闭;若不关闭,高并发情况下回造成数据库访问缓慢


三  应用

          Spring配置:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context
="http://www.springframework.org/schema/context"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xmlns:tx
="http://www.springframework.org/schema/tx"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
>

  <!-- 数据源配置-->

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${jdbc.driverClassName}" />
        <property name="jdbcUrl" value="${jdbc.url}" />
        <property name="user" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="autoCommitOnClose" value="true"/>
        <property name="checkoutTimeout" value="${cpool.checkoutTimeout}"/>
        <property name="initialPoolSize" value="${cpool.minPoolSize}"/>
        <property name="minPoolSize" value="${cpool.minPoolSize}"/>
        <property name="maxPoolSize" value="${cpool.maxPoolSize}"/>
        <property name="maxIdleTime" value="${cpool.maxIdleTime}"/>
        <property name="acquireIncrement" value="${cpool.acquireIncrement}"/>
        <property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}"/>
  </bean>

   

<!--   Hibernate常规配置-->

    <!--Hibernate SessionFatory-->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocations">
            <list>
                <value>classpath*:/config/hibernate.cfg.*.xml</value>
            </list>
        </property>
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                <prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>
            </props>
        </property>
    </bean>

    <!--Hibernate TransactionManager:hibernate事务管理-->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
    </bean>


<!-- 属性文件(jdbc,hibernate配置文件参数值)读入 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath*:config/jdbc.properties</value>
                <value>classpath*:config/hibernate.properties</value>
            </list>
        </property>
    </bean>

    <!-- 支持 @Transactional 标记 -->
    <tx:annotation-driven/>

    <!-- 支持 @AspectJ 标记-->
    <aop:aspectj-autoproxy/>

    <!-- 以AspectJ方式 定义 AOP -->
    <aop:config proxy-target-class="true">
        <!-- <aop:advisor pointcut="execution(* org.my431.core..*Manager.*(..))" advice-ref="txAdvice"/> -->
        <aop:advisor pointcut="execution(* org.my431.base..*Manager.*(..))" advice-ref="txAdvice"/>
    </aop:config>

    <!-- 基本事务定义,使用transactionManager作事务管理,默认get*方法的事务为readonly,其余方法按默认设置.
             默认的设置请参考Spring文档事务一章. -->
    <tx:advice id="txAdvice">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>
   

</beans>

注:在进行事务配置时,切面扫描范围要写正确,否则会以下错误:
   org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here


execution 中第一个*表示任何返回类型.

execution(* com.myd.spring.daoImp.*.*(..)):com.myd.spring.daoImp下子包任意任意返回类型的方法
execution(public * com.myd.spring.daoImp.*.*(..)):com.myd.spring.daoImp下子包任意任意返回类型的公有(public)方法


另外:多线程访问情况下,为了方便会使用this.getHibernateTemplate().getSessionFactory().getCurrentSession()方法,省去手动释放事务的工作,但是仍会报以下错误,所以需要用HibernateDaoSupport的getSession()方法,并手动this.releaseSession()方法释放。

 


四总结

                     spring进行事务管理有多种配置方式,处理bean代理机制(公用代理,单个代理)稍作修改,数据源配置,事务管理器变化不大。在进行配置的时候,要根据需求决定配置方式

0 0
原创粉丝点击