You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SpringBoot项目启动时出现org.hibernate.mapping.Bag无法转换为org.hibernate.mapping.SimpleValue错误求助

SpringBoot项目启动时出现org.hibernate.mapping.Bag无法转换为org.hibernate.mapping.SimpleValue错误求助

嗨,看起来你遇到的这个ClassCastException确实和Hibernate处理实体继承以及关联映射的方式有关,我帮你梳理下可能的问题点和解决办法:

一、先解析核心错误的根源

java.lang.ClassCastException: class org.hibernate.mapping.Bag cannot be cast to class org.hibernate.mapping.SimpleValue这个错误,本质是Hibernate在解析实体映射时,误把集合类型(Bag是Hibernate对List集合的内部映射类型)当成了普通的单值属性来处理。结合你提到的继承问题,大概率是继承策略配置不完整加上关联映射的小冲突导致的。

二、针对性修复步骤

1. 完善JPA继承策略配置

你试过@Inheritance(strategy = InheritanceType.SINGLE_TABLE)但没解决问题,大概率是因为缺少了区分父子类的鉴别器配置。Hibernate用单表继承时,需要明确标识每条记录属于哪个实体类,否则会导致映射解析混乱:

  • 在父类Etape上补充鉴别器注解:
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
// 添加鉴别器列,用来区分父类和子类的记录
@DiscriminatorColumn(name = "etape_type", discriminatorType = DiscriminatorType.STRING)
public class Etape {
    @Id
    // 明确MySQL的自增策略,避免Hibernate默认策略的兼容性问题
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @OneToMany(mappedBy = "etape", cascade = CascadeType.REMOVE)
    private List<Remarque> remarques;
    
    @ManyToOne()
    @JoinColumn(name = "idProjet")
    private Project project;
    
    @Column()
    private int termine;
}
  • 在子类Etape1上指定鉴别器值:
package com.application.model.etapes.Etape1;

import com.application.model.etapes.Etape;
import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.List;

@EqualsAndHashCode(callSuper = true)
@Data
@Entity
// 指定当前子类对应的鉴别器值
@DiscriminatorValue("ETAPE1")
public class Etape1 extends Etape {

    @Column(columnDefinition = "TEXT")
    private String attr1;
    
    @Column()
    private String attr2;
    
    @Column()
    private boolean attr3;

    @OneToMany(mappedBy = "etape1", cascade = CascadeType.REMOVE)
    private List<Beneficiare> beneficiares;
    
    @OneToMany(mappedBy = "etape1", cascade = CascadeType.REMOVE)
    private List<Objectif> objectifs;
    
    @OneToMany(mappedBy = "etape1", cascade = CascadeType.REMOVE)
    private List<VeilleGlobal> veilleGlobals;
    
    @OneToOne(mappedBy ="etape1" ,  cascade = CascadeType.REMOVE)
    private Mission mission;
}

2. 校验关联映射的正确性

确保所有mappedBy对应的关联实体字段存在且名称完全匹配:

  • 比如Etape里的remarques对应Remarque实体中的@ManyToOne字段etape
  • Etape1里的beneficiares对应Beneficiare实体中的@ManyToOne字段etape1,以此类推。

举个Beneficiare的正确配置示例:

@Entity
public class Beneficiare {
    // ... 其他字段
    @ManyToOne
    @JoinColumn(name = "etape1_id")
    private Etape1 etape1;
}

如果字段名不匹配,Hibernate无法正确解析关联关系,也会引发类似的类型转换错误。

3. 优化Docker Compose的数据库启动逻辑

虽然这不是直接导致错误的原因,但数据库未就绪时启动Spring Boot可能会引发其他异常干扰排查。你可以给数据库服务添加健康检查,确保后端服务在数据库完全就绪后再启动:

修改docker-compose.yml

version: "3.7"
services:
  backend:
    build: ./backend
    networks:
      - shared-net
    environment:
      - spring.datasource.url=jdbc:mysql://application-db:3306/db?allowPublicKeyRetrieval=true&useSSL=false
    ports:
      - 82:8080
    depends_on:
      application-db:
        condition: service_healthy

  application-db:
    image: "mysql:latest"
    restart: always
    ports:
      - 3306:3306
    networks:
      - shared-net
    environment:
      MYSQL_ROOT_PASSWORD: '' 
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes" 
      MYSQL_DATABASE: db 
    volumes:
      - ./db:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

networks:
  shared-net:

4. 清理重置数据库表结构

如果之前的表结构因为错误的继承策略已经混乱,可以删除本地的./db目录(Docker挂载的MySQL数据卷),然后重新启动容器,让Hibernate基于正确的配置重新生成表结构(确保你的spring.jpa.hibernate.ddl-auto配置为createupdate)。

三、额外检查点

  • 确认Spring Boot和Hibernate的版本兼容:不同版本的Hibernate对JPA注解的解析逻辑可能有差异,尽量使用Spring Boot推荐的依赖版本;
  • 检查是否有重复的字段名:父子类中如果有同名字段(即使类型不同),也可能导致Hibernate映射解析错误。

按照上面的步骤一步步排查,应该能解决你遇到的问题。

备注:内容来源于stack exchange,提问作者M0ngi

火山引擎 最新活动