簡體   English   中英

如何使用父實體的組合鍵進行JPA @OneToMany單向映射?

[英]How can I do a JPA @OneToMany unidirectional mapping with the parent entity's composite key?

當前,這些只是查詢操作,如果您“獲取”父級,則希望獲取所有子級。 它是遺留的遺留數據庫(DB2),其中父表中的三個字段是其組合PK。 子表具有這三個字段,另外一個作為其組合PK。

無需雙向。 只需要讓孩子和父母一起。

@Entity @IdClass(ParentId.class)
class Parent {
    @Id int someId
    @Id int someCode
    @Id Date someDate

    @OneToMany(fetch = FetchType.EAGER, ???)
    ???
    List<Child> children
}

class ParentId implements Serializable {
    int someId
    int someCode
    Date someDate
}

@Entity @IdClass(ChildId.class)
class Child {
    @Id int someId
    @Id int someCode
    @Id Date someDate
    @Id String childValue
    ...
}

class ChildId implements Serializable {
    int someId
    int someCode
    Date someDate
    String childValue
}

ChildId類非常類似於父類和另一個字段。

我需要切換到@Embeddable和@EmbeddableId等嗎? 無論如何,任何人都有如何使這項工作的想法? 我看過的例子更加簡單化,似乎對我不起作用。

我可以更改Parent和Child類,但不能更改表及其當前的組合PK。

您可以使用@IdClass@EmbeddedId 無論哪種方式,您都在使用“派生身份”。 這是使用@IdClass的可能解決方案:

@Entity
@IdClass(ParentId.class)
public class Parent {
    @Id int someId;
    @Id int someCode;
    @Id Date someDate;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "parent")
    List<Child> children;
}

public class ParentId implements Serializable {
    int someId;
    int someCode;
    Date someDate;
    ...
}

@Entity
@IdClass(ChildId.class)
public class Child {
    @Id
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="PARENT_ID", referencedColumnName="someId"),
        @JoinColumn(name="PARENT_CODE", referencedColumnName="someCode"),
        @JoinColumn(name="PARENT_DATE", referencedColumnName="someDate") 
    })
    Parent parent;
    @Id String childValue;
    ...
}

public class ChildId implements Serializable {
    ParentId parent; // matches name of attribute and type of Parent Id class
    String childValue;
}

JPA 2.1規范的第2.4.1節中討論了派生身份。

您可以繼續使用@IdClass進行單向映射 為此,您可以在Parent類的List<Child> children字段上添加@JoinColumns({...)}以及cascade屬性,如下所示:

@Entity @IdClass(ParentId.class)
class Parent {
    @Id int someId;
    @Id int someCode;
    @Id Date someDate;

    @OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
    @JoinColumns({
        @JoinColumn(name="someId", referencedColumnName="someId"),
        @JoinColumn(name="someCode", referencedColumnName="someCode"),
        @JoinColumn(name="someDate", referencedColumnName="someDate") 
})    
    List<CKChild> children = new ArrayList<>();
}
class ParentId implements Serializable {
    int someId;
    int someCode;
    Date someDate;
}

@Entity @IdClass(ChildId.class)
class Child {
    @Id int someId;
    @Id int someCode;
    @Id Date someDate;
    @Id String childValue;
}

class ChildId implements Serializable {
    int someId;
    int someCode;
    Date someDate;
    String childValue;
}

但是,更好的主意是按照Brian的回答中的說明,使用帶有mappedBy 雙向映射

從執行的DML語句開始,它是有效的。 隨着Unidirectional你會看到每一個額外的更新語句children實體 List<Child> ,同時節省了Parent 而且使用Bidirectional時,不會導致此額外的更新語句。

更新:

我的測試代碼檢索:

session = openSession();
tx = session.beginTransaction();
System.out.println(session.createQuery("select p from Parent p").list());
tx.commit();

並給我以下

Hibernate: select ckparent0_.someCode as someCode1_1_, ckparent0_.someDate as someDate2_1_, ckparent0_.someId as someId3_1_ from Parent ckparent0_
Hibernate: select children0_.someCode as someCode2_0_0_, children0_.someDate as someDate3_0_0_, children0_.someId as someId4_0_0_, children0_.childValue as childVal1_0_0_, children0_.childValue as childVal1_0_1_, children0_.someCode as someCode2_0_1_, children0_.someDate as someDate3_0_1_, children0_.someId as someId4_0_1_ from Child children0_ where children0_.someCode=? and children0_.someDate=? and children0_.someId=?
Hibernate: select children0_.someCode as someCode2_0_0_, children0_.someDate as someDate3_0_0_, children0_.someId as someId4_0_0_, children0_.childValue as childVal1_0_0_, children0_.childValue as childVal1_0_1_, children0_.someCode as someCode2_0_1_, children0_.someDate as someDate3_0_1_, children0_.someId as someId4_0_1_ from Child children0_ where children0_.someCode=? and children0_.someDate=? and children0_.someId=?
**Retrieved :** [org.hibernate.bugs.Parent@1e17ad20, org.hibernate.bugs.Parent@7111ca49]

使用以下DDL

Hibernate: create table Child (childValue varchar(255) not null, someCode integer not null, someDate timestamp not null, someId integer not null, primary key (childValue, someCode, someDate, someId))
Hibernate: create table Parent (someCode integer not null, someDate timestamp not null, someId integer not null, primary key (someCode, someDate, someId))
Hibernate: alter table Child add constraint FKl06s6kkl5xx2s82tlbsh160vo foreign key (someCode, someDate, someId) references Parent

因此,首先,這是Groovy,上面的代碼有點暗示,但我沒有明確提及。 這要求注釋使用方括號“ []”而不是大括號“ {}”來指定數組屬性,例如@JoinColumn。

除此之外,它比我想象的要簡單。 對於具有相同字段的單向關系,我不需要指定實際的列名或引用的列名。 只是常見的字段名稱。

我還切換到Set並按在數據庫中指定鍵的順序放置@JoinColumns。 最后兩件事可能並不重要。

@Entity @IdClass(ParentId.class)
class Parent {
    @Id int someCode
    @Id Date someDate
    @Id int someId

    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumns([@JoinColumn(name = "someCode"),
        @JoinColumn(name = "someDate"),
        @JoinColumn(name = "someId")])
    Set<Child> children
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM