Parent Id null in @OneToMany mapping JPA
Asked Answered
J

3

12

I am using javax.persistence.OneToMany relationship in a Parent Child relationship. The parent Id is coming as null, I have read through all the related post in Stackoverflow but not getting any clue what I am missing. All the Corresponding PKs are getting populated in both Parent & Child tables as per the Sequence Provided, but the FK is set to null in Child table

Parent Class:

@Entity
@Table(name = "DIVERSITY_TEMPLATE")
public class DiversityTemplate implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name = "DIVERSITY_TEMPLATE_ID", sequenceName = "DIVERSITY_TEMPLATE_ID", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "DIVERSITY_TEMPLATE_ID")
    @Column(name = "DIVERSITY_TEMPLATE_ID")
    private Integer diversityTemplateId;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "diversityTemplate", fetch = FetchType.LAZY)
    private List<DiversityTemplateAttribute> attributes = new ArrayList<>();

Child Class:

@Entity
@Table(name = "DIVERSITY_TEMPLATE_ATTRIBUTE")
@TypeName("DiversityTemplateAttribute")
public class DiversityTemplateAttribute implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name = "DIVERSITY_TEMPLATE_ATTR_ID", sequenceName = "DIVERSITY_TEMPLATE_ATTR_ID", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "DIVERSITY_TEMPLATE_ATTR_ID")
    @Column(name = "DIVERSITY_TEMPLATE_ATTR_ID")
    private Integer diversityTemplateAttributeId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "DIVERSITY_TEMPLATE_ID", nullable=false, referencedColumnName = "DIVERSITY_TEMPLATE_ID")
    private DiversityTemplate diversityTemplate;

Service Class:

 diversityTemplateRepository.save(diversityTemplate);

Sample json

{
  "diversityTemplateId": 0,
  "attributes": [{
    "diversityTemplateId": 0,
    "diversityTemplateAttributeId": 0,
  }, {
    "diversityTemplateId": 0,
    "diversityTemplateAttributeId": 0,
  }]
}

Please suggest.

Justin answered 11/4, 2017 at 22:45 Comment(0)
F
11

Usually empty FK columns are coming from setting only one side of the relation.

I imagine you have the following

DiversityTemplate diversityTemplate = ...
diversityTemplate.getAttributes().add(...)
...
diversityTemplateRepository.save(diversityTemplate);

This is wrong because the DiversityTemplateAttribute doesn't know about the parent, only the parent know about his children.

Solving this is easy, you have to set the parent reference in the child.

diversityTemplateAttribute.setDiversityTemplate(diversityTemplate);

Or you can put this logic into a method within the DiversityTemplate which automatically adds the attribute into the List + sets the backreference.

Fustigate answered 12/4, 2017 at 6:29 Comment(1)
Thanks @galovics, it works now, I have added the back reference in the Parent Class as below, Thanks a ton for you advice. public void setAttributes(List<DiversityTemplateAttribute> attributes) { for (DiversityTemplateAttribute diversityTemplateAttribute : attributes) { diversityTemplateAttribute.setDiversityTemplate(this); } this.attributes = attributes; }Justin
S
12

I know it's too late but you can also do...

Parent Class:

@Entity
@Table(name = "DIVERSITY_TEMPLATE")
public class DiversityTemplate implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name = "DIVERSITY_TEMPLATE_ID", sequenceName = "DIVERSITY_TEMPLATE_ID", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "DIVERSITY_TEMPLATE_ID")
    @Column(name = "DIVERSITY_TEMPLATE_ID")
    private Integer diversityTemplateId;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "DIVERSITY_TEMPLATE_ID")
    private List<DiversityTemplateAttribute> attributes = new ArrayList<>();

Child Class:

@Entity
@Table(name = "DIVERSITY_TEMPLATE_ATTRIBUTE")
@TypeName("DiversityTemplateAttribute")
public class DiversityTemplateAttribute implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name = "DIVERSITY_TEMPLATE_ATTR_ID", sequenceName = "DIVERSITY_TEMPLATE_ATTR_ID", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "DIVERSITY_TEMPLATE_ATTR_ID")
    @Column(name = "DIVERSITY_TEMPLATE_ATTR_ID")
    private Integer diversityTemplateAttributeId;

    @ManyToOne(fetch = FetchType.LAZY)
    private DiversityTemplate diversityTemplate;

Service Class:

diversityTemplateRepository.save(diversityTemplate);

This way you DON'T NEED TO DO PARENT ENTRY IN EACH CHILD. it will do by itself. you just need to save parent that's it.

Quick steps what I did.

  1. Removed mappedBy from Parent.
  2. Added @JoinCollumn foreign key in Parent
  3. Removed @JoinCollumn from Child.

Hope it helps.

Saltation answered 12/4, 2019 at 7:24 Comment(6)
Could one parent still have several children with this solution?Kroon
Thanks a lot! And yes it works for serveral childrenGumwood
Wow! It really works. All the tutorials have it wrong, imagine that.Enigmatic
This should be accepted answerConstitution
This is the correct way and should be the accepted answer. @OPBobbybobbye
Don't work for me :'( Schema-validation: missing table (Join table required)Edraedrea
F
11

Usually empty FK columns are coming from setting only one side of the relation.

I imagine you have the following

DiversityTemplate diversityTemplate = ...
diversityTemplate.getAttributes().add(...)
...
diversityTemplateRepository.save(diversityTemplate);

This is wrong because the DiversityTemplateAttribute doesn't know about the parent, only the parent know about his children.

Solving this is easy, you have to set the parent reference in the child.

diversityTemplateAttribute.setDiversityTemplate(diversityTemplate);

Or you can put this logic into a method within the DiversityTemplate which automatically adds the attribute into the List + sets the backreference.

Fustigate answered 12/4, 2017 at 6:29 Comment(1)
Thanks @galovics, it works now, I have added the back reference in the Parent Class as below, Thanks a ton for you advice. public void setAttributes(List<DiversityTemplateAttribute> attributes) { for (DiversityTemplateAttribute diversityTemplateAttribute : attributes) { diversityTemplateAttribute.setDiversityTemplate(this); } this.attributes = attributes; }Justin
C
0
@JsonManagedReference 
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "DIVERSITY_TEMPLATE_ID")
    private List<DiversityTemplateAttribute> attributes = new ArrayList<>();
.
.
.
.
@JsonBackRefrence
 @ManyToOne(fetch = FetchType.LAZY)
    private DiversityTemplate diversityTemplate;

these JsonManagedReference and JsonBackReference are provided by jackson library to let the JPA know on which class it should serialize and on which it shouldnt... so that we can avoid Infinite recursion... more about this in here!

Capacitance answered 16/2, 2022 at 7:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.