У меня есть отношения между родителями и детьми OneToOne, но два из них. Аннотации не очень хороши, но выдает хорошую схему БД, но код не работает. Если я пытаюсь сохранить экземпляр Parent, Hibernate сначала пытается сохранить child1 и child2 - но он нарушает FK, определенный в Child ->, поскольку владелец еще не существует в БД ... Поэтому мне нужно сохранить Parent, а затем child1, и child2.
Если бы я мог сделать это, это не помогло, потому что, когда я пытаюсь загрузить Parent, Hibernate не будет знать, какая запись в таблице Child принадлежит child1 или child2 ... Так что в этом случае мне нужно будет указать одно условие в соединении для child1 что-то типа "где тип = 1" и для child2 "где тип = 2" ...
Просто чтобы уточнить: в таблице Child
будет ноль или один ребенок на одного Parent
с ChildType.A
(всегда child1) и ноль или один ребенок с ChildType.B
(всегда child2).
Мне нужно сохранить XML, который выглядит следующим образом:
<parent id="" oid="">
<child1 (and other attributes)>
<child2 (and other attributes)>
<parent>
Оба элемента child1
и child2
имеют одинаковый тип, поэтому имеют тип Child
в классах Java. Разница только в названии элемента (в Java я различаю их с ChildType
). Только идентификация для детей - это атрибуты id
и oid
от родителя. Они указывают на другой Parent
, следовательно, target
в Child
.
Мне нужно как-то изменить аннотации, чтобы это работало ... У вас, ребята, есть идеи, потому что я действительно застрял ???
Parent.java
public class Parent {
private String oid
private Long id;
private Child child1;
private Child child2;
@Id
@GeneratedValue(generator = "IdGenerator")
@GenericGenerator(name = "IdGenerator", strategy = "com.example.IdGenerator")
@Column(name = "id")
public Long getId() {
return id;
}
@Id
@GeneratedValue(generator = "OidGenerator")
@GenericGenerator(name = "OidGenerator", strategy = "com.example.OidGenerator")
@Column(name = "oid", nullable = false, updatable = false, length = 36)
public String getOid() {
return oid;
}
@OneToOne(optional = true, fetch = FetchType.EAGER)
@Cascade({org.hibernate.annotations.CascadeType.ALL})
public Child getChild1() {
return child1;
}
@OneToOne(optional = true, fetch = FetchType.EAGER)
@Cascade({org.hibernate.annotations.CascadeType.ALL})
public Child getChild2() {
return child2;
}
}
Child.java
public class Child {
private Parent owner;
private String ownerOid;
private Long ownerId;
private ChildType type;
private Parent target;
@MapsId("owner")
@ManyToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumns({
@PrimaryKeyJoinColumn(name = "owner_oid", referencedColumnName = "oid"),
@PrimaryKeyJoinColumn(name = "owner_id", referencedColumnName = "id")
})
public Parent getOwner() {
return owner;
}
@MapsId("target")
@ManyToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumns({
@PrimaryKeyJoinColumn(name = "target_oid", referencedColumnName = "oid"),
@PrimaryKeyJoinColumn(name = "target_id", referencedColumnName = "id")
})
public Parent getTarget() {
return target;
}
@Id
@Column(name = "owner_id")
public Long getOwnerId() {
if (ownerId == null && owner != null) {
ownerId = owner.getId();
}
return ownerId;
}
@Id
@Column(name = "owner_oid", length = 36)
public String getOwnerOid() {
if (ownerOid == null && owner != null) {
ownerOid = owner.getOid();
}
return ownerOid;
}
@Id
@Column(name = "target_id")
public Long getTargetId() {
if (targetId == null && target != null) {
targetId = target.getId();
}
return targetId;
}
@Id
@Column(name = "target_oid", length = 36)
public String getTargetOid() {
if (targetOid == null && target != null) {
targetOid = target.getOid();
}
if (targetOid == null) {
targetOid = "";
}
return targetOid;
}
@Id
@Enumerated(EnumType.ORDINAL)
public ChildType getType() {
if (type == null) {
return ChildType.A;
}
return type;
}
}
ChildType.java
public enum ChildType {
A, B;
}
Я также пытался использовать mappedBy
подход mappedBy подход , но все еще есть проблемы с загрузкой - я не могу сказать hibernate, какая дочерняя запись belogs для какой переменной дочернего элемента класса.