做了一个ssh的小项目,事务控制是通过spring在配置文件里统一控制的。但是发现运行一段时间后就出现“java.sql.SQLException: ORA-00018: 超出最大会话数”问题。
我怀疑是dao中的方法没有被事务控制,以至于session没有释放,导致问题。
     以下是我spring中关于数据库的配置,希望大家能提些意见。
     我先对配置进行一下说明。有一个BaseService所有的service包括(ServicesImpl等都继承这个类),BaseService的作用是get和set“DAO”,即取得DAO的bean。
     我对各个service的事务控制是起作用的,主要用来控制多个相关存操作的事务。 所以我会对dao也会起到事务控制。 
     我的代码中经常出现这样的代码service.getEmployeeDAO().save(name)。这样的操作是不是通过这个spring配置控制了事务。
     总之,我的程序运行一阶段就出现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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
default-autowire="byName">
<!-- 数据库的hibernate配置 -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"
value="oracle.jdbc.driver.OracleDriver">
</property>
<property name="jdbcUrl"
value="jdbc:oracle:thin:@12.61.14.61:1521:KPI">
</property>
<property name="user" value="user"></property>
<property name="password" value="pass"></property>
<property name="maxPoolSize" value="40" />
<!-- 指定连接数据库连接池的最小连接数 -->
<property name="minPoolSize" value="1" />
<!-- 指定连接数据库连接池的初始化连接数 -->
<property name="initialPoolSize" value="1" />
<!-- 指定连接数据库连接池的连接的最大空闲时间 -->
<property name="maxIdleTime" value="20" />
</bean> <bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"></ref>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="format_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>
com/rdc/hibernate/bean/Processkpcontract.hbm.xml
</value>
                                 ...........
</list>
</property>
</bean> <!-- 声明services -->
<bean id="service" class="com.rdc.struts.service.ServicesImpl"></bean>
<bean id="serviceC" class="com.rdc.struts.service.ServicesImpl_C"></bean>
<bean id="serviceL" class="com.rdc.struts.service.ServicesImpl_L"></bean>
<bean id="serviceZ" class="com.rdc.struts.service.ServicesImpl_Z"></bean>
<bean id="serviceF" class="com.rdc.struts.service.ServicesImpl_F"></bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <!-- 事务拦截器 -->
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean> <bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>service</value>
<value>serviceC</value>
<value>serviceL</value>
<value>serviceZ</value>
<value>serviceF</value>
</list>
</property>
<property name="interceptorNames">
<value>transactionInterceptor</value>
</property>
<property name="proxyTargetClass">
<value>true</value>
</property>
</bean> <bean name="daoTemplate" abstract="true">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
        .........................
</beans>

解决方案 »

  1.   

    session是自己用自己关的,一个DAO方法里完成了DB操作后就session.close()把它关掉
      

  2.   

    <!-- 事务拦截器 --><bean id="transactionInterceptor"
            class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
    <bean name="daoTemplate" abstract="true" lazy-init="true">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
      

  3.   

    是不是 <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>这个就不用了 lazy-init="true" ??我很多hbm.xml文件都是设成FALSE的
      

  4.   

    <!-- 事务拦截器 --> 
    名称匹配事务属性源
    <bean id="transactionInterceptor" 
          class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"> 是否延迟加载,默认false
    <bean name="daoTemplate" abstract="true" lazy-init="true"> 
            <property name="sessionFactory" ref="sessionFactory" /> 
        </bean> 
      

  5.   

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"><beans>
    <!-- 非JNDI数据源配置 -->
    <bean id="dataSource"
       class="org.apache.commons.dbcp.BasicDataSource">
       <property name="driverClassName">
        <value>oracle.jdbc.driver.OracleDriver</value>
       </property>
       <property name="url">
        <value>jdbc:oracle:thin:@localhost:1521:oemrep</value>
       </property>
       <property name="username">
        <value>test</value>
       </property>
       <property name="password">
        <value>test</value>
       </property>
    </bean>
    <!-- JNDI数据源配置 
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
       <property name="jndiName">
        <value>demoDS</value>
       </property>
    </bean>-->
    <bean id="sessionFactory"
       class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
       <property name="dataSource">
        <ref bean="dataSource" />
       </property>
       <!-- JTA事务管理的配置 
       <property name="jtaTransactionManager">
        <ref bean="webLogicServerTransactionManagerFactory"/>
       </property>-->
       <property name="hibernateProperties">
        <props>
         <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
         <prop key="hibernate.show_sql">true</prop>
         <prop key="hibernate.cglib.use_reflection_optimizer">false</prop>
         <prop key="hibernate.jdbc.fetch_size">50</prop>
         <prop key="hibernate.jdbc.batch_size">20</prop>
         <prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop>
         <!-- <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
         <prop key="hibernate.cache.use_query_cache">true</prop> -->
        </props>
       </property>
       <property name="mappingDirectoryLocations">
        <list>
         <!-- 添加hibernate值对象的路径名 -->
         <value>classpath:/com/htxx/demo/model</value> 
        </list>
       </property>
    </bean><!--hibernate事务管理 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <property name="sessionFactory">
        <ref bean="sessionFactory" />
       </property>
    </bean><bean id="transactionManagerJDBC" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource">
        <ref local="dataSource"/>
       </property>
    </bean>
    <!-- JtaTransactionManager不需要知道 DataSource 和其他特定的资源,因为它将使用容器提供的全局事务管理 
    <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
       <property name="userTransaction"><ref bean="webLogicServerTransactionManagerFactory"/></property>
    </bean>-->
    <!-- WebLogic服务器事务管理工厂 
    <bean id="webLogicServerTransactionManagerFactory" class="org.springframework.transaction.jta.WebLogicServerTransactionManagerFactoryBean">
    </bean>--><!-- 事务拦截器 --> 
        <bean id="transactionInterceptor" 
            class="org.springframework.transaction.interceptor.TransactionInterceptor"> 
            <property name="transactionManager" ref="transactionManager" /> 
            <property name="transactionAttributeSource"><ref bean="defaultTxAttributes"/></property> 
        </bean><!-- 事务属性源 -->
    <bean id="defaultTxAttributes"
       class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
       <property name="properties">
        <props>
         <prop key="create*">PROPAGATION_REQUIRED</prop>
         <prop key="delete*">PROPAGATION_REQUIRED</prop>
         <prop key="update*">PROPAGATION_REQUIRED</prop>
         <prop key="modify*">PROPAGATION_REQUIRED</prop>
         <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
        </props>
       </property>
    </bean><bean id="InvoiceTxAttributes"
       class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
       <property name="properties">
        <props>
         <prop key="create*">PROPAGATION_REQUIRED</prop>
         <prop key="delete*">PROPAGATION_REQUIRED</prop>
         <prop key="update*">PROPAGATION_REQUIRED</prop>
         <prop key="cancel*">PROPAGATION_REQUIRED</prop>
         <prop key="accountIn">PROPAGATION_REQUIRED</prop>
         <prop key="accountOut">PROPAGATION_REQUIRED</prop>
         <prop key="*">PROPAGATION_SUPPORTS</prop>
        </props>
       </property>
    </bean><!-- 名称匹配的自动代理创建器,所有名字以Bus,Service结尾的bean都将为其创建事务拦截,注释此处就不再被自动事务处理 --> 
        <bean name="beanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> 
            <property name="beanNames">
                <value>*Bus,*Service</value> 
            </property> 
            <property name="interceptorNames"> 
                <list> 
                    <!-- 可以增加其他的拦截器 --> 
                    <value>transactionInterceptor</value> 
                </list> 
            </property> 
        </bean>
        
        <!-- ehcache缓存处理 -->
    <!-- <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
       <property name="configLocation">
         <value>classpath:ehcache.xml</value>
       </property>
    </bean><bean id="methodCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
       <property name="cacheManager">
         <ref local="cacheManager"/>
       </property>
       <property name="cacheName">
         <value>defaultCache</value>
       </property>
    </bean> -->
    </beans>
      

  6.   

    鼓励使用spring2.0的事务配置方式,简单了一些,改了一下你的配置如下:
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 数据库相关 -->
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
        default-autowire="byName">
        <!-- 数据库的hibernate配置 -->
    ......
        <!-- 声明services -->
        <bean id="service" class="com.rdc.struts.service.ServicesImpl"></bean>
        <bean id="serviceC" class="com.rdc.struts.service.ServicesImpl_C"></bean>
        <bean id="serviceL" class="com.rdc.struts.service.ServicesImpl_L"></bean>
        <bean id="serviceZ" class="com.rdc.struts.service.ServicesImpl_Z"></bean>
        <bean id="serviceF" class="com.rdc.struts.service.ServicesImpl_F"></bean>
        <bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    </bean> <tx:advice id="txAdvice">
    <tx:attributes>
    <tx:method name="insert*"propagation="REQUIRED"/>
    <tx:method name="find*"propagation="REQUIRED" read-only="true"/>
    <tx:method name="*"propagation="REQUIRED"/>
    </tx:attributes>
    </tx:advice>
    <aop:config>
    <aop:pointcut id="fooServiceOperation"
    expression="execution(* com.rdc.struts.service.*.*(..))" />
    <aop:advisor advice-ref="txAdvice"
    pointcut-ref="fooServiceOperation" />
    </aop:config>    <bean name="daoTemplate" abstract="true">
        </bean>
            .........................
        </beans>java中直接获取service、serviceC即可
    先测试一下吧,最好用getHibernateTemplate来进行dao层的增删改查,看是否存在不释放连接的情况
    备注:建议用proxool连接池
      

  7.   

    忘记修改schema了,把beans 节点换成
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:p="http://www.springframework.org/schema/p"

    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.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
    ......
      

  8.   

    请使用spring提供的针对hibernate的事务管理类,否则sessionFactory,session没法管理
    DataSourceTransactionManager对此无法管理<bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
    TO:--------------><bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <property name="sessionFactory">
        <ref bean="sessionFactory" />
       </property>
    </bean>
      

  9.   


     <bean id="transactionManager"
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        </bean>
    这个没用上啊    <bean name="daoTemplate" abstract="true">
    这个也没。。
      

  10.   

    transactionManager用上了呀
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    只不过这里省略了,如果名字是transactionManager就不用写daoTemplate这个你在service里面怎么注入,还是一样的呀
      

  11.   

    transactionManager用上了呀
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    只不过这里省略了,如果名字是transactionManager就不用写
    其实transactionManager是这么写的
    <bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    但是你如果默认是byName的话,里面的property就可以省略daoTemplate这个你在service里面怎么注入,还是一样的呀
      

  12.   


    <!--hibernate事务管理 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <property name="sessionFactory">
        <ref bean="sessionFactory" />
       </property>
    </bean><bean name="daoTemplate" abstract="true">
       <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <bean name="daoTemplate" abstract="true">
       <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    package com.rdc.hibernate.dao;import java.util.Date;
    import java.util.List;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.hibernate.LockMode;
    import org.springframework.context.ApplicationContext;
    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import com.rdc.hibernate.bean.Achieveevaluate;/**
     * Data access object (DAO) for domain model class Achieveevaluate.
     * 
     * @see com.rdc.hibernate.bean.Achieveevaluate
     * @author MyEclipse Persistence Tools
     */public class AchieveevaluateDAO extends HibernateDaoSupport { public void save(Achieveevaluate transientInstance) {
    log.debug("saving Achieveevaluate instance");
    try {
    getHibernateTemplate().save(transientInstance);
    log.debug("save successful");
    } catch (RuntimeException re) {
    log.error("save failed", re);
    throw re;
    }
    } public void update(Achieveevaluate transientInstance) {
    log.debug("updating Achieveevaluate instance");
    try {
    getHibernateTemplate().update(transientInstance);
    log.debug("update successful");
    } catch (RuntimeException re) {
    log.error("update failed", re);
    throw re;
    }
    }
    }
    如果dao如上面代码所示 ,是不是这3条语句就可以控制dao中的save了。
      

  13.   

    public class AchieveevaluateDAO extends HibernateDaoSupport { public void save(Achieveevaluate transientInstance) {

    try {
                     getHibernateTemplate().save(transientInstance);
    } catch (RuntimeException re) {
    throw re;
    }
    }}<!--hibernate事务管理 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <property name="sessionFactory">
        <ref bean="sessionFactory" />
       </property>
    </bean>
    <bean name="daoTemplate" abstract="true">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean><bean id="achieveevaluateDAO"
         class="com.rdc.hibernate.dao.AchieveevaluateDAO" parent="daoTemplate">
    </bean>
    上面spring的配置是不是就可以控制achieveevaluateDAO这个dao中的save事务,实现session的关闭。
      

  14.   

    是否实现事务是看你的service方法是否在事务中
    expression="execution(* com.rdc.struts.service.*.*(..))" />如果你在com.rdc.struts.service包下的类的业务方法中调用dao方法,那么就包含在事务中
    你可以看日志,事务在log中是否启动,写的很清楚