【发布时间】:2015-08-10 20:10:28
【问题描述】:
我有一对实体,称它们为“Ticket”和“TicketComment”。
Ticket 有这个属性:
@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);
我认为在没有重复子实体的情况下,我之前已经能够使用类似实体成功地做到这一点......我可能会遗漏什么?
更新:一种解决方法似乎是:
- 为“TicketComment”创建另一个 JpaRepository
- 在不使用
ticketRepo创建/添加评论的情况下将任何其他更新保存到票证。 - 创建新评论,与工单 (
newComment.setTicket(ticket);) 关联,并使用ticketCommentRepo保存。
所以,有两种不同的保存,一种只应该影响父母,另一种应该只影响孩子。
我想将其简化为一次保存,但我不确定这是否可行?
更新 2:澄清观察到的症状。
如果我尝试简单地保存我的父“Ticket”实体并添加新的“TicketComment”,我会看到在数据库中创建了两条不同的记录,它们具有不同的主键,但具有相同的注释文本,并且相同,或几乎如此,时间戳。
例如,假设我发表了“看起来不错”之类的评论。即使我在调试器中确认在我的ticket.getComments() 中只显示一个“看起来不错”...在我再次加载工单的详细信息页面后,我看到如下内容:
我@2015-09-11 23:16:58:看起来不错
我@2015-09-11 23:16:59:看起来不错
当我查看正在准备的 SQL 语句的一些调试日志时,我看到我的 TicketComments 表调用了两个看起来相同的 INSERT 语句,然后是我的 Tickets 表的单个 UPDATE...
【问题讨论】:
-
你能分享你的ticketRepo findOne 和保存方法吗?
-
那些是由 Spring Data JPA 生成的。
-
那之后你会保存 newComment 吗?
-
您是否使用 Hibernate 作为 JPA 提供程序?
-
那么,这是an earlier post 的副本。您被 Hibernate 错误击中。链接的帖子有多种解决方法,包括在将子实体添加到父实体之前保存子实体、使用
Set而不是List等。
标签: java jpa spring-data-jpa