简体   繁体   中英

New child entity is getting created while Updating Parent in OneToMany JPA

Hi I have a Parent Child tables as below. There are below problems. I am using Spring Data Repository (org.springframework.data.repository)

Question 1 While I am Persisting the Parent child entries are getting inserted as well, but while I am trying to update the the Parent (Where new changes are present both in parent & child), new child entries are getting inserted in child table with the updated data instead of updating the old child data.

Question 2 I am making a patch call here , the data is coming from UI as json, I have some audit trail fields like createdBy, createdTimestamp, updatedBy, updatedTimestamp. These fields are getting populated in backend service in Create & Update operations respectively. Now in update operation, my dto don't have any values for createdBy & createdTimestamp, so in DB it is getting set as null.I am confused here, I am using a patch call then it should retain the old value right ?

Please suggest If I have missed any

Parent:

@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;

@Column(name = "LABEL")
private String label;

@Column(name = "RELATIONSHIP_TYPE")
private String relationshipType;

@Column(name = "CREATED_BY")
private String createdBy;

@Column(name = "CREATED_TIMESTAMP")
@Temporal(TemporalType.TIMESTAMP)
private Date createdTimestamp;

@Column(name = "UPDATED_BY")
private String updatedBy;

@Column(name = "UPDATED_TIMESTAMP")
@Temporal(TemporalType.TIMESTAMP)
private Date updatedTimestamp;

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

/**
 * @return the attributes
 */
public List<DiversityTemplateAttribute> getAttributes() {
    return attributes;
}

/**
 * @param attributes the attributes to set
 */
public void setAttributes(List<DiversityTemplateAttribute> attributes) {
    for (DiversityTemplateAttribute diversityTemplateAttribute : attributes) {
        diversityTemplateAttribute.setDiversityTemplate(this);
    }
    this.attributes = attributes;
}

Child:

@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;

@Column(name = "AA")
private String aa;

@Column(name = "BB")
private String bb;

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

Sample Update JSON

{
"diversityTemplateId": 681,
"label": "SAMPLE_LABEL_463_UPDATED",
"relationshipType": "Married",
"attributes": [{
    "diversityTemplateId": 681,
    "diversityTemplateAttributeId": 3006,
    "aa": "AA",
    "bb": "BB Updated",
}, {
    "diversityTemplateId": 681,
    "diversityTemplateAttributeId": 3006,
    "aa": "aa Updated",
    "bb": "bb"
}
]

}

Service Layer:

DiversityTemplate updatedEntity = diversityTemplateRepository.save(diversityTemplate);

Question 3 In case of Mapping back the Entity object (when I get it from GET/CREATE operation) to DTO object I am not able to set the FK id in child object , So as a workaround I am iterating through the child list of objects & setting the pk of parent in the child DTO manually, is there any better way of doing this. I have added anothe transient column in the child ENTITY class with same pk Column name as in Parent, but then also it's value is coming as zero, is there any better way ? Please find below my work around.

DiversityTemplate updatedEntity = diversityTemplateRepository.save(diversityTemplate);

    List<DiversityTemplateAttributeDTO> attrbiteList = new ArrayList<>();
    for (DiversityTemplateAttribute attribute : updatedEntity.getAttributes()) {
        DiversityTemplateAttributeDTO attributeDTO = resourceMapper
                .convertToDiversityTemplateAttributeDTO(attribute);
        attributeDTO.setDiversityTemplateId(updatedEntity.getDiversityTemplateId());
        attrbiteList.add(attributeDTO);
    }

    DiversityTemplateDTO updatedDiversityTemplateDTO = resourceMapper.convertToDiversityTemplateDTO(updatedEntity);
    diversityTemplateDTO.setAttributes(attrbiteList);

Please suggest

I had all the same issues as you.

Answer 1: What I ended up doing was setting the orphanRemoval flag equal to true on the @OneToMany. if you do this just be aware that you can no longer set that list of children equal to a new list or else it will through and error. You have to remove and append depending on what you want to delete and add.

Answer 2: You are missing the @EntityListeners(AuditingEntityListener.class) at the top of you parent class but just in case that doesn't work, here is a link to what I used to get it working https://dzone.com/articles/spring-data-jpa-auditing-automatically-the-good-stuff

Answer 3: The reason the id is not setting is because in the java code you have to set the reference to the parent in the child. ie child.setDiversityTemplate(parent); Once you do that it will properly map it in the table and you'll be able to retrieve it no problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM