目前这些只是查询操作,如果您“获取”父项,您希望获取所有子项。遗留数据库(DB2)是遗留数据库(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等?无论如何,任何人都有想法如何使这项工作?我见过的例子比较简单,似乎对我不起作用。
我可以更改父类和子类,但不能更改表及其当前的复合PK。
答案 0 :(得分:1)
您可以使用@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节中讨论。
答案 1 :(得分:1)
您可以使用单向映射继续@IdClass
。为此,您可以在@JoinColumns({...)}
类的cascade
字段中添加List<Child> children
和Parent
属性,如下所示:
@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;
}
但是,更好的想法是使用双向映射与mappedBy
一起使用,如Brian的回答所示。
从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
答案 2 :(得分:0)
首先,这是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
}