gpt4 book ai didi

Java Hibernate 连接泄漏

转载 作者:太空宇宙 更新时间:2023-11-04 07:50:49 25 4
gpt4 key购买 nike

使用Hibernate和Struts2,整个流程如下:

hibernate.cfg.xml 为:

<hibernate-configuration>

<session-factory>
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="connection.url">jdbc:oracle:thin:@xx.xx.xxx.xx:1521:TEST</property>
<property name="connection.username">xxxx</property>
<property name="connection.password">xxxxyyy</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>

<mapping class="test.models.administration.Menus" />

<mapping resource="Dual.hbm.xml" />
</session-factory>

</hibernate-configuration>

对于 DAO 的扩展 AbstractSimpleGenericDao:

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;

@SuppressWarnings("unchecked")
public abstract class AbstractSimpleGenericDao<C, I extends Serializable> {

Class<C> entityClass;

@SessionTarget
protected Session hSession;

@TransactionTarget
protected Transaction hTransaction;

{
entityClass = (Class<C>) ((ParameterizedType)
getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

public List<C> getAll()
{
try
{
return hSession.createCriteria(entityClass).list();
}
catch (HibernateException e)
{
throw e;
}
}

public C get(I id)
{
try
{
return (C) hSession.get(entityClass, id);
}
catch (HibernateException e)
{
throw e;
}
}

public void save(C object)
{
try
{
hSession.save(object);
}
catch (HibernateException e)
{
hTransaction.rollback();
throw e;
}
}

public void update(C object)
{
try
{
hSession.update(object);
}
catch (HibernateException e)
{
hTransaction.rollback();
throw e;
}
}

public void delete(I id)
{
try
{
C actual = get(id);
hSession.delete(actual);
}
catch (HibernateException e)
{
hTransaction.rollback();
throw e;
}
}
}

然后在我的 DAO 类中扩展上面 DAO,如下所示:

       public class UserRoleDAO extends AbstractSimpleGenericDao<UserRole, UserRoleId> {

public List L() {
try {
String queryString = "from UserRole";
Query queryObject = hSession.createQuery(queryString);
return queryObject.list();
} catch (RuntimeException re) {
throw re;
}
}

然后在我的struts Action类中,实例化DAO并检索列表:

          public class abc extends ActionSupport{
private UserRoleDAO userRoleDao = new UserRoleDAO();
private List ls=new ArrayList();
public String execute()
{
List ls=userRoleDao.L()
return "success";
}
}

如果我通过重复单击指定的菜单链接来调用此 abc 操作类,则会导致连接泄漏,算作我可以使用 jProfiler 看到的打开的连接,并且永远不会关闭。同时,它还存在泄漏连接。

使用 jProfiler 记录所有打开的泄漏连接的StackTrace:

org.hibernate.transaction.JDBCTransaction.begin()

com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.injectHibernateTransactionByAnnotation(java.lang.Object, org.hibernate.Session, boolean)

com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.injectHibernateTransactionByAnnotation(java.lang.Object, org.hibernate.Session, boolean)

com.googlecode.s2hibernate.struts2.plugin.interceptors.SessionTransactionInjectorInter
ceptor.intercept(com.opensymphony.xwork2.ActionInvocation)

java.lang.Thread.run()
URL: /project/action-name

为什么 Hibernate 会泄漏这些连接?

是不是,Hibernate 将连接保留在 session 中并重用相同的连接,因此,如果同时发出并发请求,如果 session 连接被占用,则会泄漏连接。这只是我的假设。我不知道。

最佳答案

在您的 hibernate 配置中隐式使用DriverManagerConfigurationProvider。默认情况下使用此提供程序,除非您使用属性 connection.provider_class 配置它。

This provider also implements a very rudimentary connection pool.

“基本连接池”是什么意思。如果您运行应用程序,您可以在日志中看到

[DriverManagerConnectionProvider] Using Hibernate built-in connection pool (not for production use!)
[DriverManagerConnectionProvider] Hibernate connection pool size: 20

您还可以通过 hibernate 配置属性 connection.pool_size 设置此值。但是它不会限制您打开的最大连接数。当池为空时,您可以打开任意数量的连接。除非当前池大小不超过属性 connection.pool_size 中的值,否则提供程序将在 closeConnection 上将连接返回到池时保持它们打开状态。一旦当前池大小不为空,您就无法打开任何新连接,因为连接提供程序从池中返回连接。

正如您现在所看到的,很难说默认情况下使用此连接提供程序的 hibernate 可能会泄漏连接,我只是说这是不可能的。但是,它不受打开连接数的限制。

为了确保连接受到限制,请使用不同的连接提供商。例如您可以使用C3P0ConnectionProvider并设置属性hibernate.c3p0.max_size来限制打开的连接。

关于Java Hibernate 连接泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14498382/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com