仅将行删除到联接表中

时间:2019-02-17 17:42:00

标签: java spring hibernate spring-boot jpa

问题

是否可以将行删除到由@ManyToMany注释创建的联接表中?

上下文

使用此架构:

  • TAG
  • TAGS_ARTICLES
  • 文章

当从public Set<Tag> tags中删除标签(属于ARTICLE类的列表)时,也删除了TAGS_ARTICLES中相应的行,但没有删除TAG表中的标签。 / p>

唯一的方法是创建一个SQL脚本,或者JPA / Hibernate允许我们使用批注来做到这一点?

代码

我当前的代码是:article.getTags().remove(tag);

此行从列表中删除了标签,但是更改未在数据库中完成。

结论

我看到了这篇文章:How to delete a row in join table with JPA,但也必须删除相对标签(不是我的情况)。

谢谢。

编辑1:数据库中的预期结果

删除前

ARTICLE

| article_id |
| a1         |
| a2         |
| a3         |

TAGS_ARTICLES

| article_id | tag_id |
| a1         | t1     |
| a1         | t2     |
| a2         | t2     |

TAG

| article_id |
| t1         |
| t2         |

从a1标签列表中删除t1

ARTICLE

| article_id |
| a1         |
| a2         |
| a3         |

TAGS_ARTICLES

| article_id | tag_id |
| a2         | t1     |
| a2         | t2     |

TAG

| article_id |
| t1         |
| t2         |

编辑2:加入表格代码

@Entity
public class Article {
     ...
     @ManyToMany
     @JoinTable(name = "tags_articles",
        joinColumns = @JoinColumn(name = "idarticle"),
        inverseJoinColumns = @JoinColumn(name = "idtag")
     )
     private Set<Tag> tags = new HashSet<>();
     ...
}

2 个答案:

答案 0 :(得分:1)

编辑:查看评论

使用此设置应该会产生想要的结果

class Article {
   ...  

   @ManyToMany
   @JoinTable(...)
   private Set<Tag> tags = new HashSet<>();
}

class Tag {
   ...

   @ManyToMany(mappedBy = "tags")
   private Set<Article> articles = new HashSet<>();
}

Article实体已拥有该关系的所有权。


旧答案

  

public Set<Tag> tags删除标签时(ARTICLE中的列表)   类别)到TAGS_ARTICLES的相应行也被删除,但是   而不是将标签放入TAG表。

通过这种方式,我知道孤立的记录不会被删除。您想要删除它们。这是正确的吗?

您可能想尝试使用特定于Hibernate的@Cascade批注(documentation)。
只需注释您的Collection<T>字段即可。

@ManyToMany(...)
@Cascade(CascadeType.REMOVE) // or CascadeType.DELETE
private Set<Tag> tags = new HashSet<>();

请确保从org.hibernate.annotations软件包中添加它。

答案 1 :(得分:1)

实体操作的行为取决于关系的所有权,这取决于将 mappedBy 属性放置在注释中的位置。具有mappedBy的实体不是所有者。关系的双方不能是所有者。

在这里您需要确定正确的所有者。假设标签是所有者。然后,在删除标签时,关系TAGS_ARTICLES将自动更新。删除TAGS_ARTICLES时,您必须自己删除该关系。

@Entity
public class Tag{
    @ManyToMany
    Set<Tag_Articles> articles;
    //...
}

@Entity
public class Tag_Articles{
    @ManyToMany(mappedBy="articles")
    Set<Tag> tags;
    //...
}

对于上述实体关系,您可以尝试类似以下操作-

entityManager.remove(articles)
for (Tag tag: articles.tags) {
     tag.articiles.remove(articles);
}