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

Spring+Hibernate CRUD API遇同类ClassCastException异常求助

解决Spring Boot + Hibernate中因类加载器冲突导致的ClassCastException

问题场景

开发Spring Boot + Hibernate的CRUD API时,直接调用DAO的read方法能正常获取User对象,但通过Spring Controller调用时抛出ClassCastException,异常提示同一个models.User类被两个不同类加载器加载:系统类加载器('app'模块)和Spring Boot DevTools的RestartClassLoader。

核心原因

Spring Boot DevTools的热重启功能会用独立类加载器加载应用代码,若Hibernate的SessionFactory是在DevTools类加载器初始化前(比如静态工具类初始化)创建的,就会使用系统类加载器加载实体类。当Controller通过DevTools类加载器调用DAO时,Hibernate返回的User对象是系统类加载器实例,而方法返回类型是DevTools类加载器加载的User类型,导致类型转换失败。

解决方法

1. 将SessionFactory交给Spring容器管理

放弃静态工具类HibernateSessionFactoryUtil手动创建SessionFactory,让Spring统一管理,确保它使用DevTools类加载器初始化:

Hibernate配置类

@Configuration
public class HibernateConfig {
    @Bean
    public SessionFactory sessionFactory() {
        LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource());
        sessionFactoryBean.setPackagesToScan("models"); // 实体类所在包
        sessionFactoryBean.setHibernateProperties(hibernateProperties());
        sessionFactoryBean.afterPropertiesSet();
        return sessionFactoryBean.getObject();
    }

    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/your_db");
        dataSource.setUsername("db_user");
        dataSource.setPassword("db_password");
        return dataSource;
    }

    private Properties hibernateProperties() {
        Properties props = new Properties();
        props.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
        props.put("hibernate.show_sql", "true");
        props.put("hibernate.hbm2ddl.auto", "update");
        return props;
    }
}

修改UserDAO,注入SessionFactory

@Repository
public class UserDAO {
    private final SessionFactory sessionFactory;

    // 构造函数注入
    public UserDAO(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public User read(int id) {
        Transaction transaction = null;
        User user = null;
        try (Session session = sessionFactory.openSession()) {
            transaction = session.beginTransaction();
            user = session.get(User.class, id);
            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) transaction.rollback();
            e.printStackTrace();
        }
        return user;
    }
}

2. 调整DevTools类加载排除规则(保留手动创建SessionFactory时用)

在src/main/resources/META-INF/spring-devtools.properties中添加配置,确保Hibernate核心包和实体类被DevTools类加载器加载:

restart.include.hibernate=/hibernate-core-.*\.jar
restart.include.models=/your-app-artifact-id-.*\.jar

将your-app-artifact-id替换为你的Maven/Gradle项目的artifactId。

3. 清理项目缓存

执行以下操作彻底清除缓存:

  • 停止应用,执行mvn clean(Maven)或gradle clean(Gradle)
  • 删除IDE缓存目录(比如IntelliJ的.idea文件夹、Eclipse的.metadata)
  • 重新构建并启动应用

验证

修改完成后,调用/users/{id}接口,应能正常返回User对象,不再抛出ClassCastException。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:30:16