Hibernate version: Core/Annotations/EM 3.2GA
The parent id of a child in a bidirectional child owned OneToMany collection is not set correctly when the parent id is part of the child's EmbeddedId and there is a duplicate parent mapping on the child.
For example, the following code results in the Parent being inserted OK, but the child inserted with a null value for PARENT_ID.
If however I shift the ManyToOne mapping from the Child to the ChildId in place of the duplicate mapping and change the Parent's mappedBy to "id.parent" as per [#ANN-381] it works OK. That's not a good work-around for me as it means the ChildIds have to contain the full Parent object which is undesirable as they are meant to be useful as lightweight place holders for the real child object.
As far as I'm aware the duplicate mapping should work so long as it is marked updateable/insertable=false.
Code:
@Embeddable
class ChildId implements Serializable {
private Long parentId;
@Column(name = "PARENT_ID", unique = false, nullable = false, insertable = true, updatable = true)
public Long getParentId() {
return this.parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
}
@Entity(name = "Child")
@Table(name = "CHILD")
class Child implements Serializable {
private ChildId id;
private Parent parent;
@EmbeddedId
public ChildId getId() {
return this.id;
}
public void setId(ChildId id) {
this.id = id;
}
@ManyToOne(optional = false, cascade = {}, fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_ID", unique = false, nullable = false, insertable = false, updatable = false)
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
@Entity(name = "Parent")
@Table(name = "PARENT")
class Parent implements Serializable {
private Long id;
private Set<Child> children = new HashSet<Child>();
@SequenceGenerator(name = "generator", allocationSize = 10, sequenceName = "PARENT_ID_SEQ")
@Id
@GeneratedValue(strategy = SEQUENCE, generator = "generator")
@Column(name = "ID", unique = true, nullable = false, insertable = true, updatable = true)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, mappedBy = "parent")
@Fetch(FetchMode.SUBSELECT)
@Cascade( { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
}
Code:
EntityManager em = primaryEM();
Session session = (Session) em.getDelegate();
Transaction t = session.beginTransaction();
em.joinTransaction();
Parent parent = new Parent();
ChildId childId = new ChildId();
Child child = new Child();
child.setId(childId);
parent.getChildren().add(m);
child.setParent(parent);
em.persist(profile);
t.commit();