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

Java Hibernate连接payroll库报LogicalConnection已关闭异常

问题描述

在Eclipse开发环境中使用Java语言,基于Hibernate 5.5.3.Final框架开发数据库操作功能,预期连接本地payroll数据库操作student表,已导入JDBC驱动及其他所需Jar依赖包,程序运行时抛出异常无法完成操作。

报错信息
Jul 14, 2022 2:34:10 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate ORM core version 5.5.3.Final
Jul 14, 2022 2:34:11 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
Jul 14, 2022 2:34:11 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.
Jul 14, 2022 2:34:11 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/payroll]
Jul 14, 2022 2:34:11 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=root, password=****}
Jul 14, 2022 2:34:11 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Jul 14, 2022 2:34:11 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 3 (min=1)
Jul 14, 2022 2:34:11 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
Jul 14, 2022 2:34:11 PM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@304b9f1a] 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.
Hibernate: 
    select
        student0_.id as id1_0_,
        student0_.email as email2_0_,
        student0_.first_name as first_na3_0_,
        student0_.last_name as last_nam4_0_ 
    from
        student student0_
Hibernate: 
    select
        student0_.id as id1_0_0_,
        student0_.email as email2_0_0_,
        student0_.first_name as first_na3_0_0_,
        student0_.last_name as last_nam4_0_0_ 
    from
        student student0_ 
    where
        student0_.id=?
Exception in thread "main" java.lang.IllegalStateException: org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl@5eb97ced is closed
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.errorIfClosed(AbstractLogicalConnectionImplementor.java:37)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:137)
    at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:276)
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.rollback(AbstractLogicalConnectionImplementor.java:121)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.rollback(JdbcResourceLocalTransactionCoordinatorImpl.java:304)
    at org.hibernate.engine.transaction.internal.TransactionImpl.rollback(TransactionImpl.java:142)
    at models.Student.get(Student.java:131)
    at Driver.main(Driver.java:24)
相关代码

Driver主类(Driver.java)

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.*;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

import models.Student;

public class Driver {

    public static void main(String[] args) {
        Student stu =new Student();
        List<Student> students=stu.readAll();
        for(Student s: students) {
            System.out.println(s.getFirstName());           
        }
        Student s1=stu.get(4);
        System.out.println(s1.getFirstName());
    }
    

public static Session getCurrentSessionFromConfig() {
  Configuration config = new Configuration();
  config.configure();
  SessionFactory sessionFactory = config.buildSessionFactory();
  Session session = sessionFactory.getCurrentSession();
  return session;
}


public static Session getCurrentSessionX() {
  Map<String, String> settings = new HashMap<>();
  settings.put("connection.driver_class", "com.mysql.jdbc.Driver");
  settings.put("dialect", "org.hibernate.dialect.MySQL8Dialect");
  settings.put("hibernate.connection.url", 
    "jdbc:mysql://localhost/hibernate_examples");
  settings.put("hibernate.connection.username", "root");
  settings.put("hibernate.connection.password", "");
  settings.put("hibernate.current_session_context_class", "thread");
  settings.put("hibernate.show_sql", "true");
  settings.put("hibernate.format_sql", "true");

  ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                                    .applySettings(settings).build();

  MetadataSources metadataSources = new MetadataSources(serviceRegistry);
  Metadata metadata = metadataSources.buildMetadata();

  SessionFactory sessionFactory = metadata.getSessionFactoryBuilder().build();
  Session session = sessionFactory.getCurrentSession();
  return session;
}
}

Hibernate配置文件(hibernate.cfg.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC 
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
  "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost/payroll</property>
    <property name="dialect">org.hibernate.dialect.MySQL8Dialect</property>
    <property name="connection.username">root</property>
    <property name="connection.password"></property>
    <property name="connection.pool_size">3</property>
    <property name="current_session_context_class">thread</property>
    <property name="show_sql">true</property>
    <property name="format_sql">true</property>
    <property name="hbm2ddl.auto">update</property>
    <mapping class="models.Student" />
  </session-factory>
</hibernate-configuration>

SessionFactoryBuilder会话工厂类

package factories;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import models.Student;

public class SessionFactoryBuilder {
    
     private static SessionFactory sessionFactory = null;

        
     public  static SessionFactory getSessionFactory () {
         if(sessionFactory==null) {
             try {
                 Configuration cfg = new Configuration();
                    cfg.configure("hibernate.cfg.xml");
                    sessionFactory = cfg.buildSessionFactory();
             }catch(RuntimeException e) {System.out.println(e.toString());}
         }
         return sessionFactory;
     }
    public static void closeSessionFactory () {
         if(sessionFactory!=null) {
             sessionFactory.close();
         }
    }

}

Student实体类

package models;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.*;

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

import factories.SessionFactoryBuilder;

@Entity
@Table(name="student")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    int id;
    
    @Column(name="first_name")
    String firstName;
    
    @Column(name="last_name")
    String lastName;
    
    @Column(name="email")
    String email;
    
    
    public Student() {
        super();
    }
    public Student(int id, String firstName, String lastName, String email) {
        super();
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    
    public void create() {
        Session session =SessionFactoryBuilder.getSessionFactory().getCurrentSession();
        Transaction transaction= session.beginTransaction();
        session.save(this);
        transaction.commit();
        session.close();
    }
    public List<Student> readAll(){
        List<Student> studentList=new ArrayList<>();
        Session session =SessionFactoryBuilder.getSessionFactory().getCurrentSession();
        Transaction transaction= session.beginTransaction();
        studentList=(List<Student>) session.createQuery("From Student").getResultList();
        transaction.commit();
        session.close();
        return studentList;
    }
public void delete(int id) {
        Session session =SessionFactoryBuilder.getSessionFactory()
             .getCurrentSession();
        Transaction transaction= session.beginTransaction();
        Student student = session.get(Student.class, id);
        if (student != null) {
            session.delete(student);
            System.out.println("student  deleted");
        }
        transaction.commit();
        session.close();
}
public void update() {
    Session session =SessionFactoryBuilder.getSessionFactory()
         .getCurrentSession();
    Transaction transaction= session.beginTransaction();
    session.update(this);
    transaction.commit();
    session.close();
}
public Student get(int id) {
    Student stu=null;
    Transaction transaction=null;
    try(Session session =SessionFactoryBuilder.getSessionFactory()
         .getCurrentSession()){
        transaction= session.beginTransaction();
        stu=(Student) session.get(Student.class, id);       
        session.delete(stu);
        transaction.commit();
    }catch(Exception e) {
        if(transaction!=null) {
            transaction.rollback();
        }
        e.printStackTrace();
    }
    
    return stu;
}
}
故障根因
  • 核心异常触发逻辑:配置了current_session_context_class=thread时,getCurrentSession()获取的是线程绑定的Session,事务提交/回滚后框架会自动关闭该Session。代码中多处手动调用session.close(),且get()方法使用try-with-resources语法自动关闭Session,导致异常触发回滚逻辑时,连接已经被释放,抛出Connection is closed错误。
  • JDBC配置过时:使用MySQL 8.x版本时,配置的旧驱动类com.mysql.jdbc.Driver已被弃用,且连接URL缺少时区参数,存在连接兼容风险。
  • 方法逻辑错误:get()方法预期功能是按ID查询学生,内部却写了session.delete(stu)的删除逻辑,会误删表数据。
  • 异常处理缺陷:SessionFactoryBuilder初始化时捕获RuntimeException仅打印字符串,不抛出异常,初始化失败时会返回null实例,触发后续空指针问题。
修复方案
  • 修正Hibernate配置:将驱动类改为com.mysql.cj.jdbc.Driver,连接URL修改为jdbc:mysql://localhost/payroll?serverTimezone=Asia/Shanghai&useSSL=false,补充时区配置、禁用测试环境不必要的SSL校验。
  • 规范Session生命周期:删除所有CRUD方法中手动调用的session.close()代码,线程绑定的Session由框架自动管理回收,不需要手动关闭。
  • 修正get()方法逻辑:移除try-with-resources自动关闭语法,删除内部的删除数据逻辑,调整后参考代码如下:
public Student get(int id) {
    Student stu=null;
    Transaction transaction=null;
    Session session = SessionFactoryBuilder.getSessionFactory().getCurrentSession();
    try {
        transaction= session.beginTransaction();
        stu=(Student) session.get(Student.class, id);       
        transaction.commit();
    }catch(Exception e) {
        if(transaction!=null && transaction.isActive()) {
            transaction.rollback();
        }
        e.printStackTrace();
    }
    return stu;
}
  • 优化SessionFactory异常处理:初始化失败时打印完整异常栈后抛出错误,避免返回null实例。

内容的提问来源于stack exchange,提问作者Apple

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:27:25