首页 > 解决方案 > 如何修复休眠中的连接泄漏?

问题描述

我不断收到一个例外:

org.hibernate.HibernateException: The internal connection pool has reached its maximum size and no connection is currently available!

我读了这个问题,但它对我没有帮助

Java/Hibernate - 异常:内部连接池已达到其最大大小,当前没有可用的连接

所以,这是我的代码:

休眠管理器

package beans.database;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

import javax.ejb.Singleton;

/**
 * The type Hibernate manager.
 *
 */
@Singleton
public class HibernateManager {
    private StandardServiceRegistry registry;
    private SessionFactory sessionFactory;

    /**
     * Gets session.
     *
     * 
     *
     * @return the session
     */
    public Session getSession() {
        if (sessionFactory == null) {
            try {
                // Create SessionFactory
                sessionFactory = new Configuration().configure().buildSessionFactory();


            } catch (Exception e) {
                e.printStackTrace();
                if (registry != null) {
                    StandardServiceRegistryBuilder.destroy(registry);
                }
            }
        }
        final Session session = sessionFactory.openSession();
        return session;
    }

    /**
     * Shutdown.
     */
    public void shutdown() {
        if (registry != null) {
            StandardServiceRegistryBuilder.destroy(registry);
        }
    }
}

它是如何使用的

@Singleton
@LocalBean
public class FieldChecker {
@EJB
HibernateManager hibernateManager;
    public Boolean isUserFieldExist(String field, String value) {
        final Session session = hibernateManager.getSession();
        Criteria criteria = session.createCriteria(UserEntity.class);
        criteria.add(Restrictions.eq(field, value));
        criteria.setProjection(Projections.rowCount());
        long count = (long) criteria.uniqueResult();
        session.close();
        return count != 0;
    }
}

用户实体

    package entities;

import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;

@Entity
@Table(name = "user", schema = "pump_coin")
public class UserEntity {
    private long id;
    private String name;
    private String email;
    private Long phone;
    private Double height;
    private Double weight;
    private Double foot;
    private String unit;
    private Double target;
    private byte verification;
    private Timestamp date;
    private String password;
    private Integer age;
    private String sex;

    
    @Column(name = "id")
    @Id
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    
    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    
    @Column(name = "email")
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    
    @Column(name = "phone")
    public Long getPhone() {
        return phone;
    }

    public void setPhone(Long phone) {
        this.phone = phone;
    }

    
    @Column(name = "height")
    public Double getHeight() {
        return height;
    }

    public void setHeight(Double height) {
        this.height = height;
    }

    
    @Column(name = "weight")
    public Double getWeight() {
        return weight;
    }

    public void setWeight(Double weight) {
        this.weight = weight;
    }

    
    @Column(name = "foot")
    public Double getFoot() {
        return foot;
    }

    public void setFoot(Double foot) {
        this.foot = foot;
    }

    
    @Column(name = "unit")
    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    
    @Column(name = "target")
    public Double getTarget() {
        return target;
    }

    public void setTarget(Double target) {
        this.target = target;
    }

    
    @Column(name = "verification")
    public byte getVerification() {
        return verification;
    }

    public void setVerification(byte verification) {
        this.verification = verification;
    }

    
    @Column(name = "date")
    public Timestamp getDate() {
        return date;
    }

    public void setDate(Timestamp date) {
        this.date = date;
    }

    
    @Column(name = "password")
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    
    @Column(name = "age")
    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    
    @Column(name = "sex")
    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserEntity that = (UserEntity) o;
        return id == that.id && verification == that.verification && Objects.equals(name, that.name) && Objects.equals(email, that.email) && Objects.equals(phone, that.phone) && Objects.equals(height, that.height) && Objects.equals(weight, that.weight) && Objects.equals(foot, that.foot) && Objects.equals(unit, that.unit) && Objects.equals(target, that.target) && Objects.equals(date, that.date) && Objects.equals(password, that.password) && Objects.equals(age, that.age) && Objects.equals(sex, that.sex);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, email, phone, height, weight, foot, unit, target, verification, date, password, age, sex);
    }
}

休眠.cfg.xml

    <?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="connection.url">jdbc:mysql://my/url</property>
    <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
    <property name="connection.username">username</property>
    <property name="connection.password">password</property>
    <property name="hibernate.connection.pool_size">100</property>
    <property name="hibernate.c3p0.timeout">1800</property>
    <mapping class="entities.UserEntity"/>
    <mapping class="entities.CoinBalanceEntity"/>
    <!-- DB schema will be updated if needed -->
    <!-- <property name="hibernate.hbm2ddl.auto">update</property> -->
  </session-factory>
</hibernate-configuration>

我怀疑我以某种方式错误地注入了 HibernateManager,结果我得到了很多连接工厂。

标签: javahibernate

解决方案


使用 Hibernate 会话时,无论如何都必须确保始终关闭它。这意味着您的方法应该使用 try-finally 模式。

public Boolean isUserFieldExist(String field, String value) {
    final Session session = hibernateManager.getSession();
    try {
        Criteria criteria = session.createCriteria(UserEntity.class);
        criteria.add(Restrictions.eq(field, value));
        criteria.setProjection(Projections.rowCount());
        long count = (long) criteria.uniqueResult();
        return count != 0;
    } finally {
        session.close();
    }
}

您必须在使用创建新会话的任何地方执行此操作。虽然一般来说,如果您使用的是带有 EJB 注入的综合系统,您应该只注入一个EntityManager而不是像这样手动管理它。


推荐阅读