java - 在 OneToMany JPA 中更新父级时正在创建新的子实体

标签 java hibernate jpa spring-data-jpa one-to-many

您好,我有一个父子表,如下所示。存在以下问题。 我正在使用 Spring Data Repository (org.springframework.data.repository)

问题 1 当我坚持父子条目时,也会插入父子条目,但是当我尝试更新父级时(父级和子级中都存在新的更改),新的子条目将使用更新的数据插入到子表中,而不是更新旧的子数据。

问题 2 我在这里进行补丁调用,数据来自 UI 作为 json,我有一些审计跟踪字段,如createdBy、createdTimestamp、updatedBy、updatedTimestamp。这些字段分别在创建和更新操作中填充到后端服务中。现在在更新操作中,我的 dto 没有createdBy和createdTimestamp的任何值,因此在数据库中它被设置为null。我在这里很困惑,我正在使用补丁调用,那么它应该保留旧值,对吗?

如有遗漏,请提出建议

父级:

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

示例更新 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"
}
]

}

服务层:

DiversityTemplate updatedEntity = diversityTemplateRepository.save(diversityTemplate);

问题3 如果将实体对象(当我从 GET/CREATE 操作获取它时)映射回 DTO 对象,我无法在子对象中设置 FK id,因此作为一种解决方法,我迭代子对象列表并手动在子 DTO 中设置父对象的 pk,有没有更好的方法可以做到这一点。我在子 ENTITY 类中添加了另一个 transient 列,其 pk 列名称与父级中的相同,但它的值也为零,有没有更好的方法?请在下面找到我的解决方法。

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

请提出建议

最佳答案

我遇到了和你一样的问题。

答案 1:我最终所做的是将 @OneToMany 上的 orphanRemoval 标志设置为 true。如果您这样做,请注意您不能再将该子列表设置为等于新列表,否则它将通过并出错。您必须根据要删除和添加的内容来删除和追加。

答案 2:您缺少父类顶部的 @EntityListeners(AuditingEntityListener.class),但以防万一它不起作用,这里是我用来让它工作的链接 https://dzone.com/articles/spring-data-jpa-auditing-automatically-the-good-stuff

答案3:id没有设置的原因是因为在java代码中你必须在子进程中设置对父进程的引用。 即 child.setDiversityTemplate(parent); 一旦你这样做了,它就会正确地将其映射到表中,你将能够毫无问题地检索它。

关于java - 在 OneToMany JPA 中更新父级时正在创建新的子实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43404262/

相关文章:

java - 在windows 8命令行上编译Junit报错

java - 如何根据 Option 值获得 Either left/right

java - Spring中的ref与依赖属性

mysql - 为 MySql 中的 View 生成唯一长 ID

java - 了解 Spring MVC 配置

java - Hibernate 忽略自动提交错误设置。创建本地连接

java - EntityManager 的 SessionFactory 抛出异常

java - hibernate envers 对多对多关系的删除操作未得到审核

java - 按键事件不适用于 selenium webdriver 中的 chrome 浏览器

java - 容器管理的持久性上下文 : transaction-scoped vs. 扩展 - 如何决定?