I\'m using Hibernate with annotations (in spring), and I have an object which has an ordered, many-to-one relationship which a child object which has a composite primary key
Found this question searching for the answer to it's problem, but it's answers didn't solve my problem, because I was looking for @OneToMany which isn't as good of a fit for the table structure I was going after. @ElementCollection is the right fit in my case. One of the gotchas of it I believe though is that it looks at the entire row of relations as being unique, not just the rows id.
@Entity
public class ParentObject {
@Column(nullable=false, updatable=false)
@Id @GeneratedValue(generator="...")
private String id;
@ElementCollection
@CollectionTable( name = "chidren", joinColumns = @JoinColumn( name = "parent_id" ) )
private List<ObjectChild> attrs;
...
}
@Embeddable
public static class ObjectChild implements Serializable {
@Column(nullable=false, updatable=false)
private String parentId;
@Column(nullable=false, updatable=false)
private String name;
@Column(nullable=false, updatable=false)
private int pos;
@Override
public String toString() {
return new Formatter().format("%s.%s[%d]", parentId, name, pos).toString();
}
... getters and setters REQUIRED (at least they were for me)
}
After saving the Parent object, you have to explicitly set the parentId in the Child objects for the inserts on the Child objects to work.
Firstly, in the ParentObject, "fix" the mappedBy attribute that should be set to "parent". Also (but this is maybe a typo) add an @Id annotation:
@Entity
public class ParentObject {
@Id
@GeneratedValue
private String id;
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@IndexColumn(name = "pos", base=0)
private List<ObjectChild> attrs;
// getters/setters
}
Then, in ObjectChild, add a name attribute to the objectId in the composite key:
@Entity
public class ObjectChild {
@Embeddable
public static class Pk implements Serializable {
@Column(name = "parentId", nullable = false, updatable = false)
private String objectId;
@Column(nullable = false, updatable = false)
private String name;
@Column(nullable = false, updatable = false)
private int pos;
}
@EmbeddedId
private Pk pk;
@ManyToOne
@JoinColumn(name = "parentId", insertable = false, updatable = false)
private ParentObject parent;
// getters/setters
}
AND also add insertable = false, updatable = false to the @JoinColumn because we are repeating the parentId column in the mapping of this entity.
With these changes, persisting and reading the entities is working fine for me (tested with Derby).