jpa - 在JPA中,插入一个孩子并立即保存并删除该孩子不会删除数据库中的孩子
问题描述
我有一个 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。
解决方案
您面临的问题的最可能原因是双向关联未正确映射。事实上,您已经声明了两个完全不相关的关联,然后让它们共享连接列。
要正确映射双向一对多关联,您需要将“一”侧声明为相反侧,如下所示:
@OneToMany(mappedBy = "parent")
@Fetch(FetchMode.SELECT)
List<Child> children;
请注意,在这种情况下,Child
是关联的拥有方。对 的更改Parent.children
被完全忽略。
由于您似乎希望能够以Parent.children
独占方式管理关联,因此您可能希望Parent
通过删除属性来创建拥有方Child.parent
(从而将关联更改为单向关联)。
请注意,以上两个选项是唯一有效的映射。您不能同时使关联的双方成为拥有方,并且在双向一对多关联中,“一”方不能成为拥有方。
推荐阅读
- sml - 如何返回一些列表而不是普通列表?
- python - 无法在 CUDA 上下文上同步:CUDA_ERROR_NOT_INITIALIZED:Tensorflow-gpu 在 RTX 2070super 上工作非常缓慢
- javascript - 使用 Angular 应用程序向 Firebase 添加多因素 - 电话号码问题
- objective-c - SideMenu:如何包含在 Objective-C 项目中?
- servlets - Servlet 类 org.restlet.ext.servlet.ServerServlet 不是 jakarta.servlet.Servlet
- asp.net - 将值从页面传递到另一个页面 ASP.net 使用 VB
- html - Django用户认证和登录问题
- python - 比较其他熊猫数据框每一行的值
- java - CVN 14 的 ARQC/ARPC 验证
- node.js - Puppeteer:无法启动浏览器进程!产卵