3

I am trying to achieve persisting a parent object with its children. The child object has a composite key which contains a foreign key to the parent.

The current mapping is unidirectional one to many and the parent owns the relationship.

Here is my model:

Parent:

@Entity
@Table(name = "PARENT")
public class ParentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "PARENT_ID")
    private Set<Child> children;

    ...

Child:

@Entity
@IdClass(ChildPK.class)
@Table(name = "CHILD")
public class Child {

    @Id
    @Column(name = "PARENT_ID")
    private Long parentId;

    @Id
    private String source;

    @Id
    private Long alternativeId;

    ...

PK:

class ChildPK implements Serializable {

    private Long parentId;
    private String source;
    private Long alternativeId;

    ...

Currently my issue is Hibernate is not handling populating the parentId in the Child, which I think is just me being hopeful it would, and I get constraint violation on the child. I am looking for ideas on how I can achieve building the parent object containing it's children and save it all in one go.

Thanks for your help,

dapperwaterbuffalo
  • 2,672
  • 5
  • 35
  • 48

1 Answers1

2

I have asked a very similar question here. Take a look at the question and the answer (which worked).

In essence, you can try this:

@Entity
@Table(name = "PARENT")
public class ParentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @OneToMany(mappedBy="parent", cascade = CascadeType.ALL)
    private Set<Child> children = new HashSet<>();

    public void addChild(Child child){
       child.setParentId(this.id);
       children.add(child);
    }
    ...

and

@Entity
@IdClass(ChildPK.class)
@Table(name = "CHILD")
public class Child {

    @Id
    @Column(name = "PARENT_ID")
    private Long parentId;

    @Id
    private String source;

    @Id
    private Long alternativeId;

    ...

with the same ChildPk. Notice that on the Parent side we use mappedBy followed by the name of the Java property rather than @JoinColumn because the parent cannot be the owner of the association (see also this question). Also, it is useful to have an addChild method that correctly sets the properties on both sides of the relationship.

Success!

IonD
  • 93
  • 7