我们有一个页面,用户可以在其中对对象进行更改(例如:公司)。此对象具有通用字段(例如:名称,日期等)以及一些@OneToMany注释(地址,电话号码等)。
我们的要求是允许用户对前端进行更改,然后在单击按钮后保存这些更改。我们面临的问题是更新OneToMany关系。
考虑以下情况:
用户对现有地址(id:1)进行更改,他们创建一个新地址(无id项),并删除现有地址(在请求中不可见)。
请求到达后端的数据:
{
id: 1,
name: "Edited company name",
addresses: [
{
id: 1,
name: "modified address",
line1: "12 Main street"
},
{
name: "This is a new address without an id",
line1: "5 Someother Street",
}
]
}
默认情况下,我们有两个选项:
选项1:
Spring配置:
@OneToMany(fetch = FetchType.LAZY, mappedBy = "company", orphanRemoval = true)
@Cascade(org.hibernate.annotations.CascadeType.ALL)
使用此配置,删除的地址不是JSON的一部分,因此" orphanRemoval"选项确保将删除未在JSON中传递的所有地址。这里的问题是没有办法指定只删除一个地址而不是删除不属于JSON的所有公司地址。
选项2:
Spring配置:
@OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
@Cascade(org.hibernate.annotations.CascadeType.ALL)
此处的orphanRemoval选项为false(即未设置)。所以这意味着创建了新地址,更新了现有地址,但没有删除任何地址。
所以我的问题是:在Spring中有没有更好/默认的方法来实现它,或者我们是否需要手动跟踪已删除的项目并实现我们自己的逻辑以确保只有我们要删除的项目确实是删除?
P.S。
我意识到这可以通过简单地在点击按钮后进行DELETE调用和删除地址来解决,但这里的想法是我们只在用户点击" SAVE"之后才进行数据库调用。应该立即将所有更改发送到服务器。我们无法使用DELETE通话,因为如果用户决定点击"取消"我们就无法恢复这些通话。而不是保存他们的更改。
答案 0 :(得分:0)
简而言之:根据您的业务需求使用jpa并设置orphanRemoval。如果您的域模型中的地址只能存在于公司的上下文中,则您希望保留orphanRemoval标志。如果没有,你应该把它设置为假。
我用你的方法看到的问题是你想要将对象从浏览器直接合并到持久层。为了完成这项工作,您必须在json请求中传输已修改公司的所有地址。
最简单的方法是引入DTO以从域模型中分离您的webapi。这样,当您的json请求到达服务器时,您可以使用jpa加载要修改的域对象,并在一个事务中进行必要的修改。更改将在提交时写回数据库。