JPA/Spring Boot实体复用问题:嵌入不可修改实体失败
解决原生查询映射含@Embedded ChildEntity的ParentEntity问题
问题场景
我有一个原本作为独立实体的ChildEntity,现在需要重构ParentEntity,通过@Embedded来复用ChildEntity的字段,同时新增一个extra列。但执行原生查询将结果映射到ParentEntity列表时,JPA无法识别ChildEntity的字段。
现有代码结构:
原ChildEntity:
@Entity public class ChildEntity implements Serializable{ private static final long serialVersionUID = 1L; @Id @Column(name="id") private String id; @Column(name="name") private String name; //getters, setters, et al. }
重构后的ParentEntity:
@Entity public class ParentEntity implements Serializable{ private static final long serialVersionUID = 1L; @Column(name="extra") private String extra; @Embedded private ChildEntity entity; //计划给ChildEntity添加@Embeddable注解 //extra参数的getters, setters }
原生查询示例(无法正确映射):
select extra,name,id from table where (/*some condition*/)
解决方案
针对这个问题,有两种可行的处理方式,具体取决于你是否能修改ChildEntity的注解:
方式1:通过属性覆盖映射(推荐,无需修改查询语句)
- 给
ChildEntity添加@Embeddable注解(保留原@Entity,这样它既可以作为独立实体使用,也能被嵌入到其他类中):
@Entity @Embeddable public class ChildEntity implements Serializable{ private static final long serialVersionUID = 1L; @Id @Column(name="id") private String id; @Column(name="name") private String name; //getters, setters, et al. }
- 在
ParentEntity的@Embedded属性上添加@AttributeOverrides,明确指定嵌入字段对应的数据库列名:
@Entity public class ParentEntity implements Serializable{ private static final long serialVersionUID = 1L; @Column(name="extra") private String extra; @Embedded @AttributeOverrides({ @AttributeOverride(name = "id", column = @Column(name = "id")), @AttributeOverride(name = "name", column = @Column(name = "name")) }) private ChildEntity entity; //extra参数的getters, setters }
这样你的原生查询不需要做任何修改,JPA会自动将id、name列映射到ParentEntity.entity对应的字段上。
方式2:修改原生查询的字段别名
如果不想在ParentEntity中添加属性覆盖注解,也可以直接修改原生查询,给ChildEntity对应的字段加上符合嵌入属性路径的别名:
select extra as extra, name as "entity.name", id as "entity.id" from table where (/*some condition*/)
注意:别名中的点号需要用双引号包裹(不同JPA实现可能有细微差异,比如Hibernate需要引号来识别嵌套路径)。之后执行查询时,JPA就能正确将别名映射到ParentEntity.entity的对应字段。
内容的提问来源于stack exchange,提问作者user2281204
相关产品推荐
相关产品推荐

