我有两种@Entity类型。一种是文档,其中包含 PDF 的 1..n 页。另一个是标签,它为文档添加上下文或描述。例如,包含美国银行对账单的文档可能具有以下标签:BOA、STATMENT。
文档@Entity持有如下标签:
@Entity(name="document")
public class Document extends TagBearing {
...
@MappedSuperclass
public abstract class TagBearing extends LobMappedEntity {
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
protected Set<Tag> tags = new TreeSet<>();
我的 Spring Boot Web 应用程序使用 Vaadin、JPA 存储库和 Hibernate。当我手动将标签应用于文档时,或者如果我从文档中删除标签时,我会看到条目按预期到达和离开生成的 document_tags 表。但是,我有一个单独的应用程序,旨在“无头”运行并在这些文档上执行昂贵的任务,例如 PDF 页面的 OCR。这个“服务器”应用程序具有相同的 Maven 依赖项,除了 Vaadin。
当这个“服务器”应用程序运行线程操作时,它将通过 JpaRepository 命名查询加载文档,调整标签,然后 saveAndFlush。它可以毫无问题地添加一个标签或多个标签,前提是它们尚未存在于集合中。清除Set并保存不会导致记录从表中删除;尝试在集合中保存新标签会导致异常,如下所示:
2024-04-01 20:51:39.466 [Thread-7] ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Duplicate entry '781-427' for key 'document_tags.PRIMARY'
那么!我假设 Hibernate 或 JPA 管理的某些方面没有传递到这些工作线程中,因此当我清除标签然后执行
repository.saveAndFlush(document);
时,它不会级联删除操作但是 - 我该如何做到这一点?还有什么原因导致这些 @OneToMany
条目未被删除?
我在这里遇到了一些问题。
我正在外部循环中更新文档,未包含在代码片段中,并且每次保存后我都没有刷新对象。我更改了循环机制以保存、刷新,然后在保存后重新加载对象。
我将标签实体存储在 TreeSet 中,但我没有覆盖 equals / hashCode,因此该 Set 无法正确区分新记录和现有记录。
最后,@OneToMany 是错误的映射;多个Document可能有多个Tags,需要将注解改为@ManyToMany。
所有这些更改都已到位,我现在可以看到映射表中的条目在对文档对象执行操作时来来去去。