Spring+Hibernate+c3p0连接池配置-连接无法释放的问题解决方案

Spring+Hibernate+c3p0连接池配置-连接无法释放的问题解决方案

 1、Spring+Hibernate+c3p0连接池配置:

<?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:p="http://www.springframework.org/schema/p"
 xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.2.xsd
 http://www.springframework.org/schema/tx
 http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"
 default-autowire="byName">
 <context:property-placeholder location="classpath:jdbcConfig.properties" />
 <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="minPoolSize" value="5" />
  <property name="maxPoolSize" value="20" />
  <property name="maxStatements" value="10" />
  <property name="idleConnectionTestPeriod" value="3000" />
  <property name="loginTimeout" value="300" />
 </bean>
 <bean id="sessionFactory"
  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="dataSource">
   <ref local="dataSource" />
  </property>
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.show_sql">true</prop>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
    <prop key="hibernate.format_sql">true</prop>
    <prop key="hibernate.use_sql_comments">true</prop>
   </props>
  </property>
  <property name="packagesToScan" value="com" />
 </bean>
 <context:component-scan base-package="com" />
 <!-- 事务管理器 -->
 <bean id="transactionManager"
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory" />
  <property name="dataSource">
   <ref local="dataSource" />
  </property>
 </bean>
 <!-- 支持事务 @Transactional 标记 -->
 <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

2、遇到的问题:

在项目中使用this.getHibernateTemplate().getSessionFactory().openSession();获得Session进行操作数据库,但是出现当查询多次之后,连接池就满了,不会继续查询数据库,导致整个程序被挂起的情况。

具体代码如下:

public class ArticleDaoImpl implements ArticleDao {
	private HibernateTemplate hibernateTemplate;
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}
	
	public List<article> findAllArticle(int uid) {
		String sql="select * from article where auid="+uid+" and (asid=1 or asid=3 or asid=5)";
		/* 使用这种方式得到的线程不会自动关闭,当开启次数过多时,会抛出异常,导致整个程序被挂起*/
                Session session=hibernateTemplate.getSessionFactory().openSession();
		SQLQuery query=session.createSQLQuery(sql).addEntity(article.class);
		
		List<article> articleList=query.list();	
		
		return articleList;
	}
}

3、报错时候的日志信息:

2014-06-06 15:16:50,654 [btpool0-4] DEBUG AbstractBeanFactory : Returning cached instance of singleton bean 'transactionManager'
2014-06-06 15:16:50,655 [btpool0-4] DEBUG AbstractPlatformTransactionManager : Creating new transaction with name [com.*.*.service.ActivityService.findAllByPage]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2014-06-06 15:16:50,655 [btpool0-4] DEBUG HibernateTransactionManager : Opened new Session [org.hibernate.impl.SessionImpl@4bdc0bc7] for Hibernate transaction
2014-06-06 15:16:50,655 [btpool0-4] DEBUG HibernateTransactionManager : Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@4bdc0bc7]
2014-06-06 15:16:50,655 [btpool0-4] DEBUG BasicResourcePool : trace com.mchange.v2.resourcepool.BasicResourcePool@7bfbfeae [managed: 20, unused: 0, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@564389b7)
2014-06-06 15:16:50,656 [btpool0-4] DEBUG HibernateTransactionManager : Exposing Hibernate transaction as JDBC transaction [com.mchange.v2.c3p0.impl.NewProxyConnection@6a02938d]
2014-06-06 15:16:50,657 [btpool0-4] DEBUG BasicResourcePool : acquire test -- pool is already maxed out. [managed: 20; max: 20]
2014-06-06 15:16:50,657 [btpool0-4] DEBUG BasicResourcePool : awaitAvailable(): com.mchange.v2.c3p0.impl.NewPooledConnection@564389b7
2014-06-06 15:16:50,658 [btpool0-4] DEBUG BasicResourcePool : trace com.mchange.v2.resourcepool.BasicResourcePool@7bfbfeae [managed: 20, unused: 0, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@564389b7)

原来以this.getHibernateTemplate().getSessionFactory().openSession();这种方式打开的session不会自动关闭,所以查询多次之后连接池就满了,不会继续查询。

4、解决方法:

将获得session的方式从this.getHibernateTemplate().getSessionFactory().openSession();改为this.getHibernateTemplate().getSessionFactory().getCurrentSession();

具体代码如下:

public class ArticleDaoImpl implements ArticleDao {
	private HibernateTemplate hibernateTemplate;
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}
	public List<article> findAllArticle(int uid) {
		String sql="select * from article where auid="+uid+" and (asid=1 or asid=3 or asid=5)";

		Session session=hibernateTemplate.getSessionFactory().getCurrentSession();
		/* Session session=hibernateTemplate.getSessionFactory().openSession();
		 * 使用这种方式得到的线程不会自动关闭,当开启次数过多时,会抛出异常,导致整个程序被挂起*/
		SQLQuery query=session.createSQLQuery(sql).addEntity(article.class);
		
		List<article> articleList=query.list();	
		
		return articleList;
	}
}

5、获取session的几种方法的分析:

(1)this.getsession实际上是调用了父类中的方法获得session。使用spring管理hibernate的SessionFactory的时候,这个方法会从session池中拿出一个session。这样做有可能有问题,就是超session池连接数的时候,spring无法自动的关闭session。 不推荐使用。

(2)this.getHibernateTemplate().getSessionFactory().OpenSession。这种方法从spring管理的sessionFactory中创建一个session,此session不是线程绑定的。这种方法不用手动管理事务,但是同一个线程多次的开启和关闭session,浪费系统资源和影响执行效率,正常情况下还是不要用了。(需要手动关闭连接)

(3)this.getHibernateTemplate().getSessionFactory().getCurrentSession()。从spring管理的sessionFactory中创建一个绑定线程的session.,spring会根据该线程的执行情况来自动判断是关闭session还是延迟关闭。这样做可以避免手动的管理事务,同时一个线程最多开启和关闭一次session又可以提高程序的性能。 极力推荐使用这种方法。(可以完美解决本博客的问题)

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/114713.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java和C语言有什么区别?[通俗易懂]

    Java和C语言有什么区别?[通俗易懂]Java和C语言作为现在行业中经常被人提起的两种语言,有很大的区别。选择不同的语言学习以后的发展也会大不相同,那么Java和C语言有什么区别呢?现在学哪种语言更合适呢?从概念上看,C语言是一门面向过程、抽象化的通用程序设计语言;Java是一门面向对象编程语言,而Java语言是从C语言衍生而来,它吸收了C++语言的各种优点,并且摒弃了C++里难以理解的多继承、指针等概念。从概念可以看出C语言相当…

    2022年7月7日
    16
  • js数组排序的几种方法

    js数组排序的几种方法1、冒泡排序以从小到大排序为例,冒泡排序的原理就是通过两层循环把数组中两两相邻的元素进行比较,是的大的元素放到后边,元素交换位置,从而一步步的交换元素的位置,使得最大的元素放到数组的末尾,这样内部的循环就进行了一轮,再根据外部的循环依次再把次大一点的元素放到数组的末尾,从而实现数组的逐步排序。代码如下://冒泡排序vararr=[52,3,8,57,75,2,1];for(…

    2022年4月29日
    87
  • 飞鸽传书:谈谈RenderControl手动调用「建议收藏」

    飞鸽传书:谈谈RenderControl手动调用「建议收藏」有些网页需要在后台动态创建服务器控件,并且将控件的html代码写入到指定的HtmlTextWriter.如果仅是调用RenderControl方法能够将服务器控件的html内容输出,但它并不会执行OnPreRender,但是通常服务器控件都重写了OnPreRender方法,实现了许多重要的功能.我们不能将其舍弃啊.

    2022年7月21日
    7
  • 3D相机技术 | 立体视觉传感器+TOF相机「建议收藏」

    3D相机技术 | 立体视觉传感器+TOF相机「建议收藏」转自|睿慕课文章结构前言立体视觉传感器原理简介工业领域应用主流立体视觉的产品TOF相机工作原理TOF工业领域应用一些TOF研究机构1.前言在机器视觉应用中,物体三维形状的获取变得越来…

    2022年5月9日
    129
  • 【转】推荐几个免费下载激活成功教程软件的网站以及系统「建议收藏」

    【转】推荐几个免费下载激活成功教程软件的网站以及系统「建议收藏」今天想给大家推荐一些免费下载激活成功教程软件的网站,希望能帮助到大家!第一个要推荐的就CSDN自己的下载资源网站:https://download.csdn.net/推荐的原因主要是资源够全,一般网上有的这里都有,而且下载的时候能看到其他下载者的真实评价,但是有点不好的就是对新人不太友好,虽然有很多免积分的,但是一些新的资源都需要积分,不过人人为我,我为人人,在这里赚扣分也是很简单的事,只要你能上…

    2022年6月21日
    29
  • 基于STM32F4单片机对步进电机的控制(有代码)「建议收藏」

    基于STM32F4单片机对步进电机的控制(有代码)「建议收藏」步进电机是将电脉冲控制信号转变为角位移或线位移的一种常用的数字控制执行元件,又称为脉冲电机。在驱动电源的作用下,步进电机受到脉冲的控制,其转子的角位移量和速度严格地与输入脉冲的数量和脉冲频率成正比。步进电机每接收一个电脉冲,转子就转过一个相应的角度(步距角)。改变通电顺序可改变步进电动机的旋转方向;改变通电频率可改变步进电动机的转速。因此,通过控制输入电脉冲的数目、频率及电动机绕组的通电顺序就可以…

    2022年5月6日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号