【问题标题】:JPA InheritanceJPA 继承
【发布时间】:2011-08-20 14:49:32
【问题描述】:

您好,我是 JPA 新手,无法理解它如何处理继承。

我有一个特定问题需要在不更改数据库方案的情况下解决,但如果您找不到解决方案,我将不胜感激使用不同数据库方案的解决方案建议(欢迎 Hibernate/TopLink 解决方案)。

如果我不清楚或者您需要更多信息,请告诉我。提前致谢!

我有这个数据库:

TABLE Fruit
Id Varchar (10) Primary Key
size Varchar (10)
fruit_type Varchar(10)

TABLE Apple
Id Varchar (10) Primary Key Foreign Key references Fruit.Id
Apple_Property Varchar(10)

到目前为止,我的实体看起来像这样:

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="fruit_type", discriminatorType=DiscriminatorType.Char)
@DiscriminatorValue(value="fruit")

public class Fruit implements Serializable {

    @Id
    protected String Id;

    protected String size;
}

@Entity
@DiscriminatorValue(value="apple")
//@PrimaryKeyJoinColumn(name="Id" , referencedColumnName="Id")

public class Apple extends Fruit implements Serializable {

    private String Apple_Property;
}

目前我能够毫无问题地持久化 Fruit 对象.. Apple 对象仅在其 Fruit 对象尚未持久化时才会持久化。

如果我尝试使用已经持久化的 Fruit 对象来持久化苹果对象:

Fruit fruit1 = new Fruit("1", "Small");
Apple apple1 = new Apple(fruit1, "red");
provider.create(fruit1);
provider.create(apple1);

我会收到一个错误,因为 JPA 尝试在 Id="1" 的 Fruit 表上创建一个新行 已经存在了。

..

【问题讨论】:

    标签: java hibernate inheritance jpa toplink


    【解决方案1】:

    您在创建 db 表时尝试使用 java 继承概念,这在这种情况下是不可能的。我可以为这个问题考虑一种不同的方法。有表fruit_type 和fruit。 fruit_type(id, typename,desc) fruit(id, name, type_id, desc) 这里 type_id 将是外键。

    【讨论】:

    【解决方案2】:

    我认为这完全按照设计工作。当您使用联合继承并持久化一个苹果对象时,JPA 将自动插入到苹果表和水果表中。您无需在实体类中建模额外的关系或 JoinColumn。

    【讨论】:

      【解决方案3】:

      当使用 JPA 来持久化子对象(即您的情况下为 provider.create(apple1))时,一条记录将被插入到子表及其所有父表中。所以provider.create(apple1) 将向 Fruit 插入一条记录,向 Apple 表插入一条记录。

      在您的示例中,如果您只想保留一个苹果对象,只需调用 provider.create(apple1) 就足够了。它也会将水果引用保存在苹果对象中。

      顺便说一句,我建议 Fruit Table 的 PK 为数字类型,并使用@GeneratedValue 标记 Fruit bean 的 ID 字段。这样,您就可以让数据库为您生成一个ID,而不再需要在java代码中显式设置它,以避免因为在java代码中设置了一个已经存在的ID而出现“ID已存在错误”。

      【讨论】:

      • 感谢您的回复!但是..我需要能够持久化fruit1,然后创建一个由这个fruit1制成的苹果对象......但是这样做时我得到一个重复的主键错误..持久化fruit1将写入表Fruit值(1,Small ,Fruit) 稍后在持久化 apple1 时,它在表 Apple 上插入值 (1,red),但在尝试在表 Fruit 上再次插入值 (1,Small,Fruit) 时崩溃
      • 第一次持久化fruit1时,应将其持久化为apple对象而不是fruit对象。这样,指定ID的记录将同时插入到fruit和apple表中。然后,在你以后知道苹果对象的属性之后,你使用 ID 从数据库中检索苹果对象并更新它的值。
      【解决方案4】:

      我有同样的问题,到目前为止,我发现的唯一方法是查询父级并用父级构造子级。然后删除父级并重新创建两条记录。

      【讨论】:

        猜你喜欢
        • 2011-09-04
        • 2014-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-12
        • 2018-09-15
        • 2019-01-12
        • 1970-01-01
        相关资源
        最近更新 更多