Spring Boot项目Hibernate继承映射配置问题与方案咨询
核心配置错误
你当前配置第一个直接导致启动失败的问题是**@MappedSuperclass与@Entity注解不能同时标注在同一个类上**:
@MappedSuperclass用于标注非实体的父类,这类父类不会映射为独立数据库表,仅用于给子类实体复用公共字段,本身不能被其他实体关联、也不能单独执行查询- 你在Person类上同时加了这两个注解,会直接触发Hibernate的注解冲突异常
映射策略选型说明
你之前尝试的几种继承映射策略适配场景完全不同,不要硬套:
@MappedSuperclass:仅适用于父类不需要作为独立实体存在的场景,比如抽取所有表共有的id、创建时间、更新时间字段做通用基类Single Table:整个继承树的所有字段都存在同一张表中,通过鉴别器字段区分子类类型,适合子类独有字段少、对查询性能要求高的场景,缺点是子类独有字段无法设置数据库级非空约束Joined Table:父类、子类各对应一张独立表,子类表主键同时作为关联父类表的外键,查询时需要关联多表,适合遵循数据库范式、子类独有字段较多的场景
适配你当前表结构的方案
根据你给出的表结构:person表存储姓名、PESEL等通用个人信息,driver表主键id_driver同时作为外键关联person.id_person,存储司机专属的出生日期、驾照号字段,这是标准的共享主键一对一关联场景,不需要使用继承映射,直接修正实体注解即可。
修正后的代码
Person实体
删除冲突的@MappedSuperclass注解即可:
@Entity @Table(name = "person") public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id_person", nullable = false) private Integer id; @Column(name = "first_name", nullable = false, length = 200) private String firstName; @Column(name = "last_name", nullable = false, length = 200) private String lastName; @Column(name = "PESEL", nullable = false) private Integer pesel; @OneToOne(fetch = FetchType.LAZY, mappedBy = "person") private Driver driver; // 省略getter、setter }
Driver实体
修正外键关联配置,同时修复OneToMany的映射错误:
@Entity @Table(name = "driver") public class Driver { @Id @Column(name = "id_driver", nullable = false) private Integer id; @MapsId @OneToOne(fetch = FetchType.LAZY) // 指定关联person表的主键列,否则Hibernate会默认找person表中名为id的列 @JoinColumn(name = "id_driver", referencedColumnName = "id_person", nullable = false) private Person person; @Column(name = "birth_date", nullable = false) private LocalDate birthDate; @Column(name = "license", nullable = false, length = 200) private String license; // 注意:mappedBy取值为Ride实体中关联Driver的属性名,不是数据库字段名 @OneToMany(mappedBy = "driver") private Set<Ride> rides = new LinkedHashSet<>(); // 省略getter、setter }
可选:如果你一定要用继承映射
如果业务上Driver属于Person的子类,要使用Joined Table策略,需要做如下修改:
- 删除Person类中的
driver关联字段,去掉@MappedSuperclass注解,添加@Inheritance(strategy = InheritanceType.JOINED) - Driver类继承Person类,删除类中的
id、person字段,直接复用父类的主键属性
这种方案下Hibernate会自动维护两张表的主键关联,不需要手动配置@OneToOne关系。
额外注意事项
- PESEL是波兰身份证号,固定长度为11位,使用Integer类型会出现数值溢出,建议替换为String或Long类型
- 所有
mappedBy属性的取值都是对方实体类的属性名,不是数据库表的字段名,你之前写的mappedBy = "idDriver"是错误配置
内容的提问来源于stack exchange,提问作者RTM
相关产品推荐
相关产品推荐

