简体   繁体   English

一对多映射,无重复

[英]Mapping one-to-many with no duplicates

I'm attempting to do what I believe is a 'one-to-many' relationship in Jpa Spring JPA (Hibernate) where by I have three tables (Post, Tag, Post_tag). 我正在尝试做我认为在Jpa Spring JPA(休眠)中的“一对多”关系,其中我有三个表(Post,Tag,Post_tag)。

One post may have many tags, and multiple posts may share the same tag as well as other tags. 一个帖子可能有多个标签,多个帖子可能会共享相同的标签以及其他标签。 Where tags overlap, there should only be one instance of that tag in the tag table. 标签重叠的地方,标签表中应该只有该标签的一个实例。

The structure goes a little like the following: 该结构类似于以下内容:

Post: 发布:

  • id ID
  • name 名称

Post_tag: Post_tag:

  • post_id post_id
  • tag_id tag_id

Tag: 标签:

  • id ID
  • tag 标签

My understanding is that this is a 'many-to-one' relation from the Post's perspective, and a 'one-to-many' from the Tags perspective. 我的理解是,从邮政的角度来看,这是“一对多”的关系,而从“标签”角度来看,这是“一对多”的关系。 Currently I've managed to make this work using a Many-To-One relationship, however this is producing many identical tags with different IDs and cluttering the database slowing it down and making me result in caching results in redis an attempt to speed up queries which is a temporary fix! 目前,我已经设法使用多对一关系来完成这项工作,但是,这会产生许多具有不同ID的相同标签,并且会使数据库混乱,从而使其减慢速度,并使我产生缓存结果,从而导致Redis尝试加快查询速度这是一个临时解决方案!

What I currently have is: 我目前拥有的是:

@Table(name="Post")
public class Post implements Serializable {

...

@ManyToOne(targetEntity = Tags.class, cascade = {CascadeType.ALL, CascadeType.MERGE})
@JoinTable(name = "post_tags",
            joinColumns = {@JoinColumn(name = "post_id")},
            inverseJoinColumns = {@JoinColumn(name = "tag_id", unique=true)})
@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="post_tags")
    public Set<Tags> tags;

And the tags table: 和标签表:

@Column(name = "tag", unique = true)
private String tag;

Thanks! 谢谢!

Your scnerio is actually a many to many relationship. 您的scnerio实际上是多对多的关系。 You better use @ManyToMany . 您最好使用@ManyToMany Something like below. 像下面这样。

@Entity
@Table(name = "Tag")

public class Tag{ 
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "Post_Tag", 
        joinColumns = { @JoinColumn(name = "tag_id") }, 
        inverseJoinColumns = { @JoinColumn(name = "post_id") }
    )
    Set<Post> posts = new HashSet<>();

    // standard constructor/getters/setters
}

@Entity
@Table(name = "Post")
public class Post{    


    @ManyToMany(mappedBy = "posts")

    private Set<Tag> tags= new HashSet<>();

    // standard constructors/getters/setters   
}

Problem is your Post is referencing your Tag table. 问题是您的帖子引用了您的标签表。 Should be your post reference your Post_Tag table to get the tag: 应该是您的帖子,引用您的Post_Tag表以获取标签:

@Entity
@Table(name = "post")
public class Post implements Serializable {

  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Integer id;
  @Column(name = "post")
  private String post;
  @OneToMany(cascade = CascadeType.ALL, mappedBy = "postId")
  private List<PostTag> postTagList;
}

@Entity
@Table(name = "tag")
public class Tag implements Serializable {

  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Integer id;
  @Column(name = "tag")
  private String tag;
  @OneToMany(cascade = CascadeType.ALL, mappedBy = "tagId")
  private List<PostTag> postTagList;
}


@Entity
@Table(name = "post_tag")
public class PostTag implements Serializable {

  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  @Column(name = "id")
  private Integer id;
  @JoinColumn(name = "post_id", referencedColumnName = "id")
  @ManyToOne(optional = false)
  private Post postId;
  @JoinColumn(name = "tag_id", referencedColumnName = "id")
  @ManyToOne(optional = false)
  private Tag tagId;
}

The above has individual post and tag entities along with the PostTag entity which references both. 上面有单独的post和tag实体,以及同时引用这两个实体的PostTag实体。

Now you can call post.getPostTagList() in a for loop to get all the tags to for the post for instance: 现在,您可以在for循环中调用post.getPostTagList()以获取帖子的所有标签,例如:

for (PostTag postTag : post.getPostTagList()) {
  Tag tag = postTag.getTag();
  String tagValue = tag.getTag();
}

One thing to note, hibernate by default lazy fetches so the list might get an error. 需要注意的一件事是,默认情况下,休眠会延迟进行懒惰获取,因此列表可能会出错。 You will have to write the query to do an eager fetch from your repository or however you fetch your data 您将必须编写查询才能从存储库中快速获取数据,或者您却获取数据

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM