使用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
相关产品推荐
相关产品推荐

