如何用Hibernate映射导入包中不可修改的父类字段?
映射外部不可修改父类字段的JPA解决方案
当父类来自外部包无法修改、不能添加@MappedSuperclass注解时,有两种标准JPA兼容的方案可以映射父类字段:
方案一:改用组合+嵌入式组件(推荐)
放弃继承关系,将父类作为子类的嵌入式组件,通过@Embedded和@AttributeOverride指定父类字段对应的数据库列。
示例代码
@Entity @Table(name = "properties_test") public class PropertyRecord { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; @Embedded @AttributeOverrides({ @AttributeOverride(name = "name", column = @Column(name = "property_name")), @AttributeOverride(name = "description", column = @Column(name = "property_desc")) // 根据Property类的实际字段,逐个添加映射规则 }) private Property property; @ManyToOne @JoinColumn(name = "dataType", referencedColumnName = "dataTypeId") private DataType dataType; @ManyToOne @JoinColumn(name = "sourceOfData", referencedColumnName = "sourceOfDataId") private SourceOfData sourceOfData; private Integer price; private Integer unitPrice; // 按需添加getter/setter,或使用Lombok的@Getter/@Setter }
注意事项
- 需要明确指定父类每个字段对应的数据库列名,避免与子类字段冲突
- 符合JPA规范,无ORM实现依赖
方案二:子类重新声明字段+属性访问
保持继承关系,在子类中重新声明父类的所有字段,通过@Access(AccessType.PROPERTY)让JPA通过getter/setter访问数据,实际读写委托给父类方法。
示例代码
@Entity @Table(name = "properties_test") @Access(AccessType.FIELD) // 子类默认使用字段访问 public class PropertyRecord extends Property { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; // 重新声明父类字段并指定映射 @Column(name = "property_name") @Access(AccessType.PROPERTY) @Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE) private String name; @Column(name = "property_desc") @Access(AccessType.PROPERTY) @Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE) private String description; @ManyToOne @JoinColumn(name = "dataType", referencedColumnName = "dataTypeId") private DataType dataType; @ManyToOne @JoinColumn(name = "sourceOfData", referencedColumnName = "sourceOfDataId") private SourceOfData sourceOfData; private Integer price; private Integer unitPrice; // 委托给父类的读写方法 public String getName() { return super.getName(); } public void setName(String name) { super.setName(name); } public String getDescription() { return super.getDescription(); } public void setDescription(String description) { super.setDescription(description); } // 子类字段的getter/setter可手动添加或用Lombok注解 }
注意事项
- 若使用Lombok的
@Data,需用@Getter(AccessLevel.NONE)和@Setter(AccessLevel.NONE)排除重新声明的父类字段,避免自动生成的方法覆盖委托逻辑 - 适合父类字段较少的场景,字段过多时维护成本较高
内容的提问来源于stack exchange,提问作者Bando
相关产品推荐
相关产品推荐

