user2176576
user2176576

Reputation: 756

Springdata jpa save OneToOne related entity with Parent's single save gives null id despite setting both directions

Using spring data jpa 2.7.5

Here are my entity relations -

@Entity
pubic class ParentEntity{
       
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "parent_id", unique = true, nullable = false, precision = 10)
    private BigDecimal parentId;
    
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "parent_id")
    private Set<ChildEntity> children;
}

@Entity
pubic class ChildEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "child_id", unique = true, nullable = false, precision = 10)
    private BigDecimal childId;
    
    ..other fields
    
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "child_id", referencedColumnName = "child_id", nullable = false)

    private Grandchild grandchild;
}

@Entity
pubic class Grandchild{

    @Id
    @Column(name = "child_id", unique = true, nullable = false, precision = 10)
    private BigDecimal childId;
    
    @Column(name = "grandchild_name", length = 60)
    private String grandchild_name;
    
    @Column(name = "grandchild_field", length = 60)
    private String grandchild_field;
}

The above class declaration gives an error - does not define an IdClass

So I modified my Entity to have an EmbeddableId with one column which is the primaty key and the foreign key childId as below -

@Entity
pubic class Grandchild{

    @EmbeddedId
    private GrandchildId grandchildId;
    
     @OneToOne(fetch = FetchType.LAZY)
     private ChildEntity childEntity ;
    
    @Column(name = "grandchild_name", length = 60)
    private String grandchild_name;
    
    @Column(name = "grandchild_field", length = 60)
    private String grandchild_field;
}

and the ID class -

@Embeddable
public class GrandchildId implements Serializable {
    @Column(name = "child_id", unique = true, nullable = false, precision = 10)
    private BigDecimal childId;
}

Now in the service I am trying to build and save parent with all its children and grandchild in a single transaction, with a single save statement building each child and adding it to set of children.

The issue is while trying to save parent in a single save statement (which is a requirement), despite maintaining the proper Cascading types, it complained of null value for childId - the primary key of Grandchild (Also the FK from ChildEntity)

Here is what I am trying to do.

Grandchild gc = new Grandchild();

gc.setGrandchildName("abc");
gc.setGrandChildField("field");

ChildEntity c = new ChildEntity();
c.setGrandChild(gc);

gc.setChild(c);

Set<ChildEntity> childSet;
childSet.add(c)

ParentEntity p = new ParentEntity();
p.setChildren(childSet);

parentRepository.save(p);

nested exception is org.springframework.orm.jpa.JpaSystemException: ids for this class must be manually assigned before calling save(): myPackage.model.Grandchild; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): myPackage.model.Grandchild] with root cause org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save():

I also tried setting the child using @PostPersist on a Child method, but it errors out with NPE before reaching there.

The accepted answer for below question says I dont need to explicitly save the enities but the null id error doesnt budge, I am looking still to call the save method only once -https://stackoverflow.com/questions/16380008/persist-onetoone-relation-with-springdata-jpa

Is there a way I can still do it in a single save? If not what are the alternatives?

Thanks!

Upvotes: 0

Views: 63

Answers (0)

Related Questions