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又可以提高程序的性能。 极力推荐使用这种方法。(可以完美解决本博客的问题)
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114713.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...