如何在Hibernate继承关系中为子类PoliceMan设置独立主键police_id?
问题描述

我定义了Person父类:
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "PERSON") public class Person { @Id @Column(name = "person_id") @SequenceGenerator(sequenceName = "PERSON_ID_SEQ", allocationSize = 1, name="PERSON_ID_SEQ") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PERSON_ID_SEQ") private Long personId; private String name; }
以及继承自Person的PoliceMan子类:
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "POLICE_MAN") public class PoliceMan extends Person{ @Id @Column(name = "police_id") private Long policeId; private String something; }
问题:父类Person已使用@Id注解,子类PoliceMan无法再用@Id将police_id设为独立唯一标识,该如何解决?
已参考过Hibernate继承相关内容,但仍未解决问题。
解决方案
根据你的需求,分两种场景给出具体解决方式:
场景1:保留继承关系,子类主键关联父类主键
这种场景下,子类PoliceMan作为特殊的Person实例,使用JOINED继承策略,子类表的主键同时作为关联父类表的外键:
- 修改父类
Person,指定继承策略
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "PERSON") @Inheritance(strategy = InheritanceType.JOINED) public class Person { @Id @Column(name = "person_id") @SequenceGenerator(sequenceName = "PERSON_ID_SEQ", allocationSize = 1, name="PERSON_ID_SEQ") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PERSON_ID_SEQ") private Long personId; private String name; }
- 调整子类
PoliceMan的主键映射
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "POLICE_MAN") @PrimaryKeyJoinColumn(name = "police_id", referencedColumnName = "person_id") public class PoliceMan extends Person{ // 移除子类的@Id注解,police_id会同时作为子类主键和关联父类的外键 private String something; }
场景2:仅复用父类属性,子类完全独立拥有主键
如果你的核心需求只是复用Person的属性,不需要将PoliceMan视为Person的实体子类,可将父类改为映射超类:
- 修改父类为非实体的映射超类
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @MappedSuperclass public class Person { // 移除@Id、@Entity等实体相关注解,仅保留属性映射 private String name; }
- 子类定义独立主键
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "POLICE_MAN") public class PoliceMan extends Person{ @Id @Column(name = "police_id") // 可根据需求添加主键生成策略,比如@GeneratedValue private Long policeId; private String something; }
额外说明
如果坚持要让police_id和person_id完全独立且保留继承关系,这种设计不符合ORM继承的语义(继承代表"is-a"关系,子类实例本质是父类实例的扩展),建议放弃继承,改为用@OneToOne或@ManyToOne关联Person类,实现两者独立主键的关联。
内容的提问来源于stack exchange,提问作者Amentos
相关产品推荐
相关产品推荐

