Part という注釈付きのエンティティがあります。「id」とその他のいくつかの変数で構成されます。「bomdefinitions」という別のテーブルがあります。このテーブルには 3 つの列 (数量、親、ターゲット) があります (ターゲットがばかげた名前であることは理解していますが、データベースが既に存在するため変更できません)。アイデアは、パーツは他の多くのパーツで構成でき、他の多くのパーツでも使用できるというものです。テーブル「bomdefinitions」には、どの親がそれに関連付けられている「ターゲット」があり、何個が使用されているかが示されています。
問題は、Part.java の OneToMany リレーションシップの 1 つをコメントアウトし、もう 1 つを残すと問題なく動作しますが、コードに両方がある場合、どちらかにアクセスしようとすると、Hibernate クエリの無限ループが発生することです。 .
エンティティをそれ自体にマッピングする例、追加の列を持つ結合テーブルを使用してエンティティをマッピングする例、および注釈を行うさまざまな方法の例を見つけることができますが、単一のアプリケーション内でそれらすべてを行うものは何もありません。ここでは役に立たないようです。
Hibernate の経験が豊富な人は、私が間違っていることについて何か考えがありますか?
編集(このコードは無限ループを引き起こします):
getHibernateTemplate().get(Part.class, id).getParentBomDefinitions();
出力のクエリは次のとおりです。次で始まります。
Hibernate: select part0_.id as id0_3_, childbomde1_.target as target0_5_, childbomde1_.parent as parent5_, childbomde1_.target as target5_, childbomde1_.parent as parent4_0_, childbomde1_.target as target4_0_, childbomde1_.qty as qty4_0_, part2_.id as id0_1_ from parts part0_ left outer join bomdefinitions childbomde1_ on part0_.id=childbomde1_.target left outer join parts part2_ on childbomde1_.parent=part2_.id
Hibernate: select parentbomd0_.parent as parent0_2_, parentbomd0_.parent as parent2_, parentbomd0_.target as target2_, parentbomd0_.parent as parent4_1_, parentbomd0_.target as target4_1_, parentbomd0_.qty as qty4_1_, part1_.id as id0_0_ from bomdefinitions parentbomd0_ left outer join parts part1_ on parentbomd0_.target=part1_.id where parentbomd0_.parent=?
次に、次の 2 つのクエリが無期限に繰り返されます。
Hibernate: select parentbomd0_.parent as parent0_2_, parentbomd0_.parent as parent2_, parentbomd0_.target as target2_, parentbomd0_.parent as parent4_1_, parentbomd0_.target as target4_1_, parentbomd0_.qty as qty4_1_, part1_.id as id0_0_ from bomdefinitions parentbomd0_ left outer join parts part1_ on parentbomd0_.target=part1_.id where parentbomd0_.parent=?
Hibernate: select childbomde0_.target as target0_2_, childbomde0_.parent as parent2_, childbomde0_.target as target2_, childbomde0_.parent as parent4_1_, childbomde0_.target as target4_1_, childbomde0_.qty as qty4_1_, part1_.id as id0_0_ from bomdefinitions childbomde0_ left outer join parts part1_ on childbomde0_.parent=part1_.id where childbomde0_.target=?
BomDefinition.java (「Java Persistence with Hibernate」からほぼ抜粋)
@Entity
@Table(name = "bomdefinitions")
public class BomDefinition {
@Embeddable
public static class Id implements Serializable {
@Column(name = "target")
private String targetId;
@Column(name = "parent")
private String parentId;
public Id() {}
public Id(String targetId, String parentId) {
this.targetId = targetId;
this.parentId = parentId;
}
public boolean equals(Object o) {
if (o != null && o instanceof Id) {
Id that = (Id) o;
return this.targetId.equals(that.targetId) && this.parentId.equals(that.parentId);
} else {
return false;
}
}
public int hashCode() {
return targetId.hashCode() + parentId.hashCode();
}
}
@EmbeddedId
private Id id = new Id();
@Column(name = "qty")
private String quantity;
@ManyToOne
@JoinColumn(name = "parent",
insertable = false,
updatable = false)
private Part parent;
@ManyToOne
@JoinColumn(name = "target",
insertable = false,
updatable = false)
private Part child;
public BomDefinition() {}
public BomDefinition(String quantity, Part parent, Part child) {
this.quantity = quantity;
this.parent = parent;
this.child = child;
this.id.parentId = parent.getId();
this.id.targetId = child.getId();
}
// Getters and Setters
}
Part.java:
@Entity
@Table(name="parts", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Part implements Serializable {
protected final Logger log = Logger.getLogger(getClass());
private String id;
// *** other variables ***
public Part() {}
public Part(String id, /* other variables */) {
this.id = id;
// *** other variables ***
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
private Set parentBomDefinitions = new HashSet(0);
private Set childBomDefinitions = new HashSet(0);
@OneToMany(mappedBy = "parent",
targetEntity = BomDefinition.class,
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.EAGER)
public Set getParentBomDefinitions() {
return parentBomDefinitions;
}
public void setParentBomDefinitions(Set<BomDefinition> parentBomDefinitions) {
this.parentBomDefinitions = parentBomDefinitions;
}
@OneToMany(mappedBy = "child", // target?
targetEntity = BomDefinition.class,
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.EAGER)
public Set getChildBomDefinitions() {
return childBomDefinitions;
}
public void setChildBomDefinitions(Set childBomDefinitions) {
this.childBomDefinitions = childBomDefinitions;
}
}