Hibernate JPA 加入继承

Posted

技术标签:

【中文标题】Hibernate JPA 加入继承【英文标题】:Hibernate JPA Joined Inheritance 【发布时间】:2015-08-04 11:59:51 【问题描述】:

我有一个项目,其中一部分数据结构是用@Inheritance(strategy = InheritanceType.JOINED) 制作的。这部分数据结构看起来像这样:

设计基于in this article.的想法 我使用带有 JPA2 接口的 Hibernate 作为我的数据层。上述结构产生了以下 pojo/dao 类(省略了 getter 和 setter):

基础项目:

@Entity
@Table( name = "base_item" )
@Inheritance(strategy = InheritanceType.JOINED)
public class BaseItemPojo 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

实体物品:

@Entity
@Table( name = "physical_item" )
public class PhysicalItemPojo extends BaseItemPojo

一些硬件:

@Entity
@Table( name = "some_hardware" )
public class SomeHardwarePojo extends PhysicalItemPojo

其他硬件:

@Entity
@Table( name = "some_other_hardware" )
public class SomeOtherHardwarePojo extends PhysicalItemPojo

这是我的问题:

我的其他表中有一个对 base_item 类的引用,如果该类基于该 base_item_id 加载“some_hardware”或“some_other_hardware”,这将使我的生活更轻松。因此,我在该特定类上创建了这样的导航属性:

@Entity
@Table( name = "some_navigation_class" )
public class SomeNavigationClassPojo
    @ManyToOne(optional = false)
    @JoinColumn(name="base_item_id", insertable = false, updatable = false)
    private BaseItemPojo baseItem;

    @ManyToOne
    @JoinColumn(name="base_item_id", insertable = false, updatable = false)
    private PhysicalItemPojo physicalItem;

    @ManyToOne()
    @JoinColumn(name = "base_item_id", insertable = false, updatable = false)
    private SomeHardwarePojo someHardwarePojo;

    @ManyToOne()
    @JoinColumn(name = "base_item_id", insertable = false, updatable = false)
    private SomeOtherHardwarePojo someOtherHardwarePojo;

正如您可能已经猜到的那样,上述方法不起作用。如果我尝试访问具有关联到实体的相关“SomeHardwarePojo”的“SomeNavigationClassPojo”,则会收到以下错误:

java.lang.IllegalArgumentException:无法将 SomeOtherHardwarePojo 字段 SomeNavigationClass.someOtherHardware 设置为 SomeHardwarePojo。

作为参考,我的目标是,如果数据库中不存在 someHardwarePojo 或 someOtherHardwarePojo,则应将它们设置为 null,而不是尝试映射到 PhysicalItemPojo 的相应其他子项

【问题讨论】:

你为什么不能只使用baseItem 属性并将所有其他属性提供为“getter”,例如getSomeHardwarePojo() return baseItem instanceof SomeHardwarePojo ? (SomeHardwarePojo) baseItem : null; 这是个好主意!我马上试一试。 @Tobias。它就像一个魅力。如果您想详细说明您的评论作为答案,并附上一个小代码示例供其他人查看,我很乐意接受它作为答案。 我只是作为评论询问,因为我担心你想在 JPA 查询中使用它们——这意味着一个更复杂的解决方案。 【参考方案1】:

您可以将属性添加为简单的 getter:

public class SomeNavigationClassPojo 
    ...
    public SomeHardwarePojo getSomeHardwarePojo()  
        return baseItem instanceof SomeHardwarePojo ? (SomeHardwarePojo) baseItem : null; 
    
    ...

主要缺点:您不能在 JPA 查询中使用属性 - 例如像SELECT n FROM SomeNavigationClassPojo n JOIN n.somehardwarepojo s WHERE s.propertyOfHardwarePojo = 'x' 这样的东西是不可能的。

【讨论】:

以上是关于Hibernate JPA 加入继承的主要内容,如果未能解决你的问题,请参考以下文章

直接加入 JPA 或 HIBERNATE

没有 id 的 JPA/Hibernate 继承

Hibernate JPA,加入多个表

如何将继承策略与 JPA 注释和 Hibernate 混合使用?

hibernate.jpa.criteria.BasicPathUsageException:无法加入基本类型的属性

JPA(休眠)映射OneToMany不正确?