在Spring-HibernateJava项目中替换类别的标记系统

在Spring-HibernateJava项目中替换类别的标记系统,java,hibernate,spring,tags,categories,Java,Hibernate,Spring,Tags,Categories,有人知道如何设计类似于stackoverflow的标签系统吗 任何能够解释如何使用hibernate/spring实现这个系统的链接都会非常棒 我只是想找个起点 我建议从三个实体开始,一个用于被标记的对象(在SO示例中,这将是一个Post),一个用于保存标记定义(您可以称之为标记),另一个用于在这两个实体之间进行映射(称之为TaggedPost) 然后,将标记分配给帖子的基本过程如下: 查看具有给定名称的标记是否已存在,如果已存在,请使用现有标记,否则请插入新标记 创建一个新的TaggedPos

有人知道如何设计类似于stackoverflow的标签系统吗

任何能够解释如何使用hibernate/spring实现这个系统的链接都会非常棒


我只是想找个起点

我建议从三个
实体开始,一个用于被标记的对象(在SO示例中,这将是一个
Post
),一个用于保存标记定义(您可以称之为
标记
),另一个用于在这两个实体之间进行映射(称之为
TaggedPost

然后,将
标记
分配给
帖子
的基本过程如下:

  • 查看具有给定名称的
    标记是否已存在,如果已存在,请使用现有标记,否则请插入新标记
  • 创建一个新的
    TaggedPost
    实例,将
    Post
    与步骤1中的
    Tag
    链接起来
  • 要从
    Post
    中删除
    Tag
    ,只需删除相应的
    TaggedPost
    实体即可


    您可以使用Hibernate注释将应用于给定
    Post
    的标记集作为Java集合公开,这样您就可以说
    getTags()
    来获取所有标记。你可以在
    标记上做同样的事情,这样你就可以说
    getPosts()
    来获取所有具有给定
    标记的帖子
    我建议从三个
    实体开始,一个用于被标记的对象(在so示例中,这将是一个
    Post
    ),一个用于保存您的标记定义(您可以将其称为
    标记
    ),另一个用于两者之间的映射(将其称为
    TaggedPost

    然后,将
    标记
    分配给
    帖子
    的基本过程如下:

  • 查看具有给定名称的
    标记是否已存在,如果已存在,请使用现有标记,否则请插入新标记
  • 创建一个新的
    TaggedPost
    实例,将
    Post
    与步骤1中的
    Tag
    链接起来
  • 要从
    Post
    中删除
    Tag
    ,只需删除相应的
    TaggedPost
    实体即可


    您可以使用Hibernate注释将应用于给定
    Post
    的标记集作为Java集合公开,这样您就可以说
    getTags()
    来获取所有标记。你可以在
    标签上做同样的事情,这样你就可以说
    getPosts()
    来获得所有具有给定
    标签的帖子,aroth的三个实体的答案是完全有效的,但是我们只使用两个实体来做同样的事情,因为第三个实体(即
    TaggedPost
    )不会为我们增加任何价值

    我们的实体看起来像这样:

    @Entity
    @Table(name = "Tag")
    public class Tag {
    
        @ManyToMany(fetch=FetchType.LAZY)
        @JoinTable(
                name="PostTag", 
                joinColumns=@JoinColumn(name="TagId"),
                inverseJoinColumns=@JoinColumn(name="PostId")
        )
        @ForeignKey(name="FK_Tag_Post", inverseName="FK_Post_Tag")
        private Set<Post> posts;
    
        /* ... */ 
    
    }
    
    
    @Entity
    @Table(name = "Post")
    public class Post {
    
        @ManyToMany
        @JoinTable(
                name="PostTag", 
                joinColumns=@JoinColumn(name="PostId"),
                inverseJoinColumns=@JoinColumn(name="TagId")
        )
        @ForeignKey(name="FK_Post_Tag", inverseName="FK_Tag_Post")
        @Sort(comparator=CompareTagByName.class, type=SortType.COMPARATOR)
        private SortedSet<Tag> tags;
    
        /* ... */ 
    
    }
    
    @实体
    @表(name=“Tag”)
    公共类标签{
    @ManyToMany(fetch=FetchType.LAZY)
    @可接合(
    name=“PostTag”,
    joinColumns=@JoinColumn(name=“TagId”),
    inverseJoinColumns=@JoinColumn(name=“PostId”)
    )
    @外键(name=“FK_标签”,inverseName=“FK_标签”)
    私人固定职位;
    /* ... */ 
    }
    @实体
    @表(name=“Post”)
    公营职位{
    @许多
    @可接合(
    name=“PostTag”,
    joinColumns=@JoinColumn(name=“PostId”),
    inverseJoinColumns=@JoinColumn(name=“TagId”)
    )
    @ForeignKey(name=“FK\u Post\u Tag”,inverseName=“FK\u Tag\u Post”)
    @排序(comparator=CompareTagByName.class,type=SortType.comparator)
    专用分类集标签;
    /* ... */ 
    }
    
    优点是我们不需要手动维护连接。我们只需根据需要在每个
    Post
    中添加或删除
    标记

    另请注意:

    • Tag.posts
      上懒抓取是个好主意。。。否则,每次显示标记时,您可能会导致Hibernate不必要地加载数千条
      Post
      记录
    • 通过提供带有
      @sort
      注释的
      比较器
      ,多对多连接使得按字母顺序对标记进行排序变得容易

    aroth对三个实体的回答是完全正确的,但我们只使用两个实体做同样的事情,因为第三个实体(即
    TaggedPost
    )不会为我们增加任何价值

    我们的实体看起来像这样:

    @Entity
    @Table(name = "Tag")
    public class Tag {
    
        @ManyToMany(fetch=FetchType.LAZY)
        @JoinTable(
                name="PostTag", 
                joinColumns=@JoinColumn(name="TagId"),
                inverseJoinColumns=@JoinColumn(name="PostId")
        )
        @ForeignKey(name="FK_Tag_Post", inverseName="FK_Post_Tag")
        private Set<Post> posts;
    
        /* ... */ 
    
    }
    
    
    @Entity
    @Table(name = "Post")
    public class Post {
    
        @ManyToMany
        @JoinTable(
                name="PostTag", 
                joinColumns=@JoinColumn(name="PostId"),
                inverseJoinColumns=@JoinColumn(name="TagId")
        )
        @ForeignKey(name="FK_Post_Tag", inverseName="FK_Tag_Post")
        @Sort(comparator=CompareTagByName.class, type=SortType.COMPARATOR)
        private SortedSet<Tag> tags;
    
        /* ... */ 
    
    }
    
    @实体
    @表(name=“Tag”)
    公共类标签{
    @ManyToMany(fetch=FetchType.LAZY)
    @可接合(
    name=“PostTag”,
    joinColumns=@JoinColumn(name=“TagId”),
    inverseJoinColumns=@JoinColumn(name=“PostId”)
    )
    @外键(name=“FK_标签”,inverseName=“FK_标签”)
    私人固定职位;
    /* ... */ 
    }
    @实体
    @表(name=“Post”)
    公营职位{
    @许多
    @可接合(
    name=“PostTag”,
    joinColumns=@JoinColumn(name=“PostId”),
    inverseJoinColumns=@JoinColumn(name=“TagId”)
    )
    @ForeignKey(name=“FK\u Post\u Tag”,inverseName=“FK\u Tag\u Post”)
    @排序(comparator=CompareTagByName.class,type=SortType.comparator)
    专用分类集标签;
    /* ... */ 
    }
    
    优点是我们不需要手动维护连接。我们只需根据需要在每个
    Post
    中添加或删除
    标记

    另请注意:

    • Tag.posts
      上懒抓取是个好主意。。。否则,每次显示标记时,您可能会导致Hibernate不必要地加载数千条
      Post
      记录
    • 通过提供带有
      @sort
      注释的
      比较器
      ,多对多连接使得按字母顺序对标记进行排序变得容易