- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一对实体,称它们为“Ticket”和“TicketComment”。
票证有这个属性:
@OneToMany(mappedBy="ticket", cascade = CascadeType.ALL)
@OrderBy("date")
private List<TicketComment> comments = new ArrayList<>();
而且,TicketComment 有这个:
@ManyToOne
@JoinColumn(name="TKT_ID")
@NotNull
private Ticket ticket;
我认为,我正在使用的代码应该添加一条新评论。但是,它似乎将新评论添加到数据库中两次:
Ticket ticket = ticketRepo.findOne(id);
TicketComment newComment = new TicketComment();
// ...
newComment.setTicket(ticket);
ticket.getComments().add(newComment);
ticketRepo.save(ticket);
我想我之前已经能够在没有重复的子实体的情况下对类似的实体成功地做到这一点......我可能会遗漏什么?
更新:解决方法似乎是:
ticketRepo
创建/添加评论。newComment.setTicket(ticket);
),并使用 ticketCommentRepo
保存。因此,有两种不同的保存方式,一种应该只影响 parent ,另一种应该只影响 child 。
我想将其简化为一次保存,但我不确定这是否可能?
更新 2:澄清观察到的症状。
如果我尝试简单地保存我的父“Ticket”实体并添加新的“TicketComment”,会发生什么情况是我看到在数据库中创建了两个不同的记录,它们具有不同的主键,但具有相同的评论文本,并且相同,或几乎如此,时间戳。
例如,假设我发布了“看起来不错”之类的评论。即使我在调试器中确认在我的 ticket.getComments()
中只显示一个“看起来不错”...在我再次加载票证的详细信息页面后,我看到如下内容:
me @ 2015-09-11 23:16:58: Looks good
me @ 2015-09-11 23:16:59: Looks good
当我查看正在准备的 SQL 语句的一些调试日志时,我看到为我的 TicketComments 表调用了两个看起来相同的 INSERT 语句,然后为我的 Tickets 表调用了一个 UPDATE...
最佳答案
我真的不明白您所说的“将新评论添加到数据库两次” 是什么意思。您是否看到两个 PK 相同的注册管理机构?
如果您希望每条评论在工单集合中出现一次,我认为您应该使用Set
接口(interface)而不是List
。无论如何,我将按部分解释我所知道的关于该代码片段的预期行为。
Ticket ticket = ticketRepo.findOne(id);
TicketComment newComment = new TicketComment();
票证已经保存了吗?没关系,因为您将 save()
它。然后你创建了一个新评论。
newComment.setTicket(ticket);
这是必要的,因为关联的所有者端位于 TicketComment
实体中,并且要保持对象模型一致(在某些情况下可能不需要)。
ticket.getComments().add(newComment);
当您在 ticket.comments
集合上设置 cascade=ALL 时,所有操作(保存、更新等)都会在 ticket
上触发将传播到集合中的所有实体对象。
ticketRepo.save(ticket);
当您将 ticket
传递给 save()
方法时,操作会传播到您刚刚添加的 newComment
实体。 newComment
将传递给 saveOrUpdate()
,然后与 ticket
的关系一起保存。
关于java - 为什么 JPA 双重插入子实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31928270/
我是一名优秀的程序员,十分优秀!