最近,我的雄猫开始挂断电话。这些请求从未得到答复。我发现这是由于连接永远不会返回到连接池。
我已经将c3p0与hibernate一起使用,数据库是mysql 5.5
为了调试连接泄漏,我在hibernate.cfg.xml
中添加了以下属性
<property name="hibernate.c3p0.unreturnedConnectionTimeout">30</property>
<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces">true</property>
添加它们后,在日志中显示:
[2013-10-12 23:40:22.487] [ INFO] BasicResourcePool.removeResource:1392 - A checked-out resource is overdue, and will be destroyed: com.mchange.v2.c3p0.impl.NewPooledConnection@1f0c0dd
[2013-10-12 23:40:22.487] [ INFO] BasicResourcePool.removeResource:1395 - Logging the stack trace by which the overdue resource was checked-out.
java.lang.Exception: DEBUG ONLY: Overdue resource check-out stack trace.
指向at dao.DAOBasicInfo.getBean(DAOBasicInfo.java:69)
public static Basicinfo getBean(Integer iduser) {
Basicinfo u = null;
Session sess = NewHibernateUtil.getSessionFactory().openSession();
try {
Transaction tx = sess.beginTransaction(); //line 69
Query q = sess.createQuery("from Basicinfo where iduser=" + iduser);
u = (Basicinfo) q.uniqueResult();
if (u == null) {
u = new Basicinfo();
u.setIduser(iduser);
}
tx.commit();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
sess.close();
}
return u;
}
我交叉检查,Mysql说它支持InnoDB的交易
由于上述错误,我有未返回的连接,然后它们堆积起来使应用程序无响应。
请让我知道开始交易有什么问题,即使我最终使用并且没有抛出异常。
调试它的一些建议
-
正如史蒂夫在评论中提到的。尝试查看删除未返回的连接超时选项时会发生什么情况。
-
可能是您的查询花费的时间太长。尝试在代码上记录一些性能统计信息,并查看查询花费了多少时间。可能需要调整查询。在短期内,您还可以将未返回的连接超时增加到超过查询的响应时间。
-
同时尝试休眠中的事务超时选项。可以设置 tx.setTimeout(20) 并使用超时数字,看看某些查询是否超时。
-
您可能还想使用一些分析工具。尝试 VisualVM,以防您的 Java 版本受支持。否则(如果在 Linux 或 Mac 上),您可能希望在旧版本的 Java 上尝试 Java 调试命令。其中一些命令也可以从 JDK 获得。
对代码的小改进
-
不确定它是否真的可以解决您的问题,但是您可能希望在异常块中添加事务回滚。为 tx.close 添加了另一个尝试捕获以避免另一个异常。
-
还添加了会话关闭的空检查。您可能已经知道,当 finally 时,一个条件可能无法完全执行 - 如果在 finally 块中抛出另一个异常。目前它可能不适用于您的代码,但是如果您在 finally 块中添加多行,请确保涵盖任何异常,以便下一行可以执行。
-
另一个建议是缩小交易本身的范围。查看代码,似乎只有在找不到 uid 的情况下,您才需要事务。如何限制 if(u==null) 块中的交易代码。不确定是否有帮助,但您不需要有事务进行读取。
下面是我的示例代码
public static Basicinfo getBean(Integer iduser) {
Basicinfo u = null;
Transaction tx = null;
Session sess = NewHibernateUtil.getSessionFactory().openSession();
try {
Query q = sess.createQuery("from Basicinfo where iduser=" + iduser);
u = (Basicinfo) q.uniqueResult();
if (u == null) {
tx = sess.beginTransaction(); //line 69
u = new Basicinfo();
u.setIduser(iduser);
tx.commit();
}
} catch (Exception ex) {
ex.printStackTrace();
if(tx != null) {
try {
tx.rollback();
} catch(Exception e){e.printStackTrace;}
}
} finally {
if(sess!=null) {
sess.close();
}
}
return u;
}
此错误的原因之一是当您不确定
transaction.commit();
不是这个问题的答案,但是忘记提交的人也会在谷歌搜索错误后登陆此页面