You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Hibernate+Servlet时遇LogicalConnectionClosed错误求助

Hibernate与Servlet整合报错排查:LogicalConnectionManagedImpl is closed

问题概述

控制台抛出如下错误,伴随浏览器加载卡顿、Tomcat重启后长时间无响应:

java.lang.IllegalStateException: org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl@1b79d968 is closed

环境与代码信息

依赖包

  • antlr-2.7.7
  • byte-buddy-1.8.17
  • classmate-1.3.4
  • dom4j-2.1.1
  • hibernate-commons-annotations-5.0.4.Final
  • hibernate-core-5.3.7.Final
  • jandex-2.0.5.Final
  • javassist-3.23.1-GA
  • javax.activation-1.2.0
  • javax.activation-api-1.2.0
  • javax.persistence-api-2.2
  • jaxb-api-2.3.0
  • jaxb-core-2.3.0
  • jaxb-impl-2.3.0
  • jboss-logging-3.3.2.Final
  • jboss-transaction-api_1.2_spec-1.1.1.Final
  • jsp-api-2.2
  • jstl-1.2
  • mysql-connector-java-8.0.13
  • protobuf-java-3.6.1
  • servlet-api-2.5

Tomcat版本

v9.0

核心代码

EmployeeHiberDAO.java

package net.employeeregjdbc.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import net.employeeregjdbc.controller.util.HibernateUtil;
import net.employeeregjdbc.model.Employee;

public class EmployeeHiberDAO {
    
    public void saveEmployee(Employee employee) {
        Transaction transaction = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            transaction = session.beginTransaction();
            session.save(employee);
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null ) transaction.rollback();
            e.printStackTrace();
        }
    }
    
    public boolean validate(String username, String password) {
        Transaction transaction = null;
        Employee employee = null;
        
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            transaction = session.beginTransaction();
            employee = (Employee) session.createQuery("FROM employee WHERE employee.username =:userNameQuery")
                    .setParameter("userNameQuery", username).uniqueResult();
            System.out.println(employee);
            if (employee != null && employee.getPassword().equals(password)) return true;
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null ) transaction.rollback();
            e.printStackTrace();
        }
        return false;
    }
}

Employee.java

package net.employeeregjdbc.model;

import java.io.Serializable;

import javax.persistence.*;

@Entity
@Table(name = "employee")
public class Employee implements Serializable {
    public Employee() {
        super();
    }
    
    private static long searialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @Column(name = "name")
    private String name;
    @Column(name = "username")
    private String username;
    @Column(name = "password")
    private String password;
    @Column(name = "note")
    private String note;
    
    public Employee(int id, String name, String username, String password, String note) {
        super();
        this.name = name;
        this.username = username;
        this.password = password;
        this.note = note;
    }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    public String getNote() { return note; }
    public void setNote(String note) { this.note = note; }
}

控制台日志

Oct 01, 2023 1:37:45 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.3.7.Final}
Oct 01, 2023 1:37:45 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Hibernate java config service registry was created
Oct 01, 2023 1:37:46 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
Oct 01, 2023 1:37:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Oct 01, 2023 1:37:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/j2ee_registration_employee_jdbc]
Oct 01, 2023 1:37:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {password=****, user=root}
Oct 01, 2023 1:37:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Oct 01, 2023 1:37:46 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Oct 01, 2023 1:37:47 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL55Dialect
Oct 01, 2023 1:37:48 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@54d13650] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Oct 01, 2023 1:37:49 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
java.lang.IllegalStateException: org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl@1b79d968 is closed
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.errorIfClosed(AbstractLogicalConnectionImplementor.java:37)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:135)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:254)
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.rollback(AbstractLogicalConnectionImplementor.java:116)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.rollback(JdbcResourceLocalTransactionCoordinatorImpl.java:294)
    at org.hibernate.engine.transaction.internal.TransactionImpl.rollback(TransactionImpl.java:139)
    at net.employeeregjdbc.dao.EmployeeHiberDAO.validate(EmployeeHiberDAO.java:44)
    at net.employeeregjdbc.controller.EmployeeLoginHiber.authenticate(EmployeeLoginHiber.java:58)
    at net.employeeregjdbc.controller.EmployeeLoginHiber.doPost(EmployeeLoginHiber.java:49)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:696)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:779)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:891)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1784)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:1589)

排查与修复步骤

1. 修正HQL语法错误

HQL基于实体类而非数据库表名,原查询中FROM employee需改为实体类名Employee,同时属性前缀可省略:

employee = (Employee) session.createQuery("FROM Employee WHERE username =:userNameQuery")
        .setParameter("userNameQuery", username).uniqueResult();

2. 修复validate方法事务逻辑

原代码中return true直接跳出方法,导致事务未提交就关闭session,后续异常回滚时连接已失效。调整逻辑先提交事务再返回结果,并增加事务活跃性检查:

public boolean validate(String username, String password) {
    Transaction transaction = null;
    Employee employee = null;
    
    try (Session session = HibernateUtil.getSessionFactory().openSession()) {
        transaction = session.beginTransaction();
        employee = (Employee) session.createQuery("FROM Employee WHERE username =:userNameQuery")
                .setParameter("userNameQuery", username).uniqueResult();
        
        boolean isValid = employee != null && employee.getPassword().equals(password);
        transaction.commit();
        return isValid;
    } catch (Exception e) {
        if (transaction != null && transaction.isActive()) {
            try {
                transaction.rollback();
            } catch (Exception rollbackEx) {
                rollbackEx.printStackTrace();
            }
        }
        e.printStackTrace();
    }
    return false;
}

3. 修正实体类序列化ID拼写错误

searialVersionUID改为serialVersionUID,并添加final修饰符:

private static final long serialVersionUID = 1L;

4. 调整依赖解决兼容性问题

  • 移除servlet-api-2.5:Tomcat 9自带Servlet 4.0 API,低版本API会引发冲突
  • 移除重复依赖:保留javax.activation-api-1.2.0,删除javax.activation-1.2.0
  • 更新MySQL驱动配置:在Hibernate配置文件中替换驱动类并添加时区参数
    hibernate.connection.driver_class=com.mysql.cj.jdbc.Driver
    hibernate.connection.url=jdbc:mysql://localhost:3306/j2ee_registration_employee_jdbc?serverTimezone=UTC
    

5. 确保SessionFactory单例实现

检查HibernateUtil,保证SessionFactory仅初始化一次,避免连接池耗尽:

public class HibernateUtil {
    private static final SessionFactory sessionFactory;
    
    static {
        try {
            Configuration configuration = new Configuration().configure();
            sessionFactory = configuration.buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
    
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

内容的提问来源于stack exchange,提问作者Huỳnh Khả Phi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 18:17:04