【问题标题】:In JPA, insert a child and save and remove the child immediately does not remove the child in database在JPA中,插入一个孩子并立即保存并删除该孩子不会删除数据库中的孩子
【发布时间】:2020-03-22 19:01:00
【问题描述】:

我有一个 Parent 实体包含一个 Childs 列表。

  • 父 A 包含子 A1
  • 交易中
    • 将 Child A2 添加到子列表中
    • 保存(不刷新)
    • 清除子列表(通过清除集合)
    • 添加子 A3
    • 保存并刷新

结果中:

  • 数据库中有两条子记录:(A1被删除)
    • 没有父信息的 A2 (==null)
    • 带有家长信息的 A3

有人可以给我一份文件来说明 JPA 是如何工作的,而不是为 A2 添加父信息吗?

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @Fetch(FetchMode.SELECT)
    @JoinColumn(name = "parent_id")
    List<Child> children;

    @Version
    private Long recordVersion;
}
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id", insertable = false, updatable = false)
    private Parent parent;

    @Version
    private Long recordVersion;

    public String toString() {
        return "Child[id=" + id + ";name=" + name + "]";
    }
}
@Transactional
    public void addChild(Long parentId, String childName) {
        Parent parent = getParent(parentId);

        Child child = new Child();
        child.setName("A2");
        List<Child> children = Arrays.asList(child);
        parent.getChildren().addAll(children);
        parentRepository.save(parent);

        parent = getParent(parentId);
        parent.getChildren().clear();

        Child child1 = new Child();
        child1.setName("A3");
        List<Child> spaces1 = Arrays.asList(child1);

        parent.getChildren().addAll(spaces1);
        parentRepository.saveAndFlush(parent);
    }

更新 1: 如果我注释掉 parentRepository.save(parent);或者用 parentRepository.saveAndFlush(parent); 替换,数据库中只有 A3。

【问题讨论】:

  • 你在 JPA 中使用什么下划线实现,如果是 Hibernate,Hibernate 中存在一个错误,导致你解释的行为hibernate.atlassian.net/browse/…
  • @MikhailChibel,我使用了 Hibernate。但是,我无法将错误映射到我的问题,您能否提供更多详细信息。谢谢。

标签: jpa spring-data


【解决方案1】:

您遇到问题的最可能原因是双向关联未正确映射。事实上,您已经声明了两个完全不相关的关联,然后让它们共享连接列。

要正确映射双向一对多关联,您需要将“一”侧声明为相反侧,如下所示:

@OneToMany(mappedBy = "parent")
@Fetch(FetchMode.SELECT)
List<Child> children;

请注意,在这种情况下,Child 是关联的拥有方。对Parent.children 的更改将被完全忽略。

由于您似乎希望能够仅使用 Parent.children 管理关联,因此您可能希望通过删除 Child.parent 属性来使 Parent 成为拥有方(从而将关联更改为单向一)。

请注意,以上两个选项是唯一有效的映射。您不能同时使关联的双方成为拥有方,并且在双向一对多关联中,“一”方不能成为拥有方。

【讨论】:

猜你喜欢
  • 2011-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 2019-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多