参考:解决spring+c3p0数据库连接一直增加的问题
这两天被数据库给搞疯了。经常报错,然后崩溃。如下
15:13:46,765 INFO CpaBreportServiceImpl:906 - org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Io 异常: Got minus one from a read call)
找了好久,还是扒日志文件发现问题总是出在CpaBreportServiceImpl中,然后看CpaBreportServiceImpl这里类,发现其中有调用这个类的这个方法
package com.ufgov.util;
import java.sql.Connection;
import javax.sql.DataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DBUtils {
private static ApplicationContext applicationContext;
/**
* 从连接池中获取一个数据库连接
*/
public static Connection getConnection() throws Exception{
applicationContext = new ClassPathXmlApplicationContext("conf/applicationContext.xml");
DataSource dataSource=applicationContext.getBean("dataSource",DataSource.class);
Connection conn=dataSource.getConnection();
return conn;
}
}
可以发现new ClassPathXmlApplicationContext("conf/applicationContext.xml")
这行代码每一次都new一个ClassPathXmlApplicationContext,那就是重新创建一次连接池(其实不只是重新创建了一次连接池,Spring管理的所有bean及其它都重新加载了一次,可以看下日志)。这样连接池的连接马上就爆掉了(这里可以监控一下数据库的连接数目,使用语句select count(1) from v$session t where t.userName='数据库用户名' and t.program='JDBC Thin Client'
可以发现每次new都会增长8个连接,这是因为BasicDataSource默认的maxActive为8,这个可以看源码。)。
那就使用spring容器来获取连接吧。
修改方式如下
package com.ufgov.util;
import java.sql.Connection;
import javax.sql.DataSource;
public class DBUtils
{
public static Connection getConnection()
throws Exception
{
DataSource dataSource = (DataSource)SpringContextUtil.getBean("dataSource");
return dataSource.getConnection();
}
}
package com.ufgov.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
*/
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
/**
* 取得存储在静态变量中的ApplicationContext.
*/
public static ApplicationContext getContext() {
checkApplicationContext();
return applicationContext;
}
/**
* 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
checkApplicationContext();
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(Class<T> clazz) {
checkApplicationContext();
return (T) applicationContext.getBeansOfType(clazz);
}
private static void checkApplicationContext() {
Assert.notNull(applicationContext,
"applicaitonContext未注入,请在applicationContext.xml中定义SpringContextUtil");
}
}
applicationContext.xml中做如下配置
<!-- 配置SpringContext工具类 -->
<bean class="com.ufgov.util.SpringContextUtil" lazy-init="false" />