cuneyttyler
cuneyttyler

Reputation: 1355

Spring Data JPA save child object with the ID of parent object

I have two objects, one parent and one child as follows :

@Entity
@Table(name="category")
public class CategoryModel {
    private @Id @GeneratedValue Long id;

    private String name;

    @OneToMany(mappedBy="category", cascade=CascadeType.PERSIST)
    private List<AttributeModel> attributes;
}

@Entity
@Table(name="attribute")
public class AttributeModel {
    private @Id @GeneratedValue Long id;

    private String name;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="category_id")
    private CategoryModel category;
}

I also have dtos which maps to these model objects but I ommited them. When I try to save a category object with this payload Attribute values are also created in the attribute table but with null category ids.

{
    "name":"Chemicals",
    "attributes":[
        {"name": "volume"}, {"name":"humidity"}
    ]
}

What can I do to have my attribute values persisted into the database with the category id which is created before them?

Upvotes: 1

Views: 5425

Answers (2)

cuneyttyler
cuneyttyler

Reputation: 1355

I solved this by manually setting child object's reference to the parent object as follows :

public Long createCategory(CategoryDto categoryDto) {
    CategoryModel categoryModel = categoryDto.toModel(true,true);
    categoryModel.getAttributes().forEach(a -> a.setCategory(categoryModel));
    return categoryRepository.save(categoryModel).getId();
}

Upvotes: 1

Ralph
Ralph

Reputation: 120791

First of all, this problem is not a "Spring Data JPA" problem, it is a JPA (probably Hibernate) problem.


Analysis

Since you left out the code for the controller and the JSON mapping, I have to guess a bit:

  • fact 1: The relationship between category and attributes is controlled by the attribute AttributeModel.category but not by CategoryModel.attributes. (That is how JPA works).
  • observation 2: Your JSON object define CategoryModel.attributes (i.e. opposite to how JPA works).

Without knowing your JSON mapping configuration and controller code, I would guess that the problem is: that your JSON mapper does not set the AttributeModel.category field when it deserialises the JSON object.


Solution

So you need to instruct the JSON mapper to set the AttributeModel.category field during deserialisation. If you use Jackson, you could use:

  • @JsonManagedReference and
  • @JsonBackReference
@Entity
@Table(name="category")
public class CategoryModel {
    ...    

    @JsonManagedReference
    @OneToMany(mappedBy="category", cascade=CascadeType.PERSIST)
    private List<AttributeModel> attributes;
}
@Entity
@Table(name="attribute")
public class AttributeModel {
    ...

    @JsonBackReference
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="category_id")
    private CategoryModel category;
}

Upvotes: 3

Related Questions