映射一对多,没有重复

时间:2018-02-12 21:12:54

标签: java mysql spring hibernate jpa

我试图在Jpa Spring JPA(Hibernate)中做我认为是'一对多'的关系,我有三个表(Post,Tag,Post_tag)。

一个帖子可能包含多个标签,多个帖子可能共享相同的标签以及其他标签。标签重叠的地方,标签表中只应该有一个该标签的实例。

结构有点像:

发表:

  • ID
  • 名称

Post_tag:

  • POST_ID
  • TAG_ID

标签:

  • ID
  • 标签

我的理解是,这是Post的视角中的“多对一”关系,以及来自Tags视角的“一对多”关系。目前我已经设法使用多对一关系来完成这项工作,但是这会生成许多具有不同ID的相同标签,并且使数据库混乱,使其速度变慢并使我在重新生成缓存结果时尝试加快查询速度这是一个临时修复!

我目前拥有的是:

@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;

标签表:

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

谢谢!

2 个答案:

答案 0 :(得分:1)

你的scnerio实际上是一对多关系。你最好用     @ManyToMany。像下面的东西。

@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   
}

答案 1 :(得分:1)

问题是您的帖子引用了您的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;
}

上面有单独的post和tag实体以及引用它们的PostTag实体。

现在你可以在for循环中调用post.getPostTagList()来获取帖子的所有标签,例如:

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

有一点需要注意,默认情况下,休眠时会进行休眠,因此列表可能会出错。您必须编写查询以从存储库中执行急切的提取,或者获取数据

相关问题