【问题标题】:How to create relationship between two tables mysqlmysql如何在两个表之间建立关系
【发布时间】:2017-01-21 10:43:34
【问题描述】:

我有两张桌子:

主题表:

CREATE TABLE `topics` (
  `id` mediumint(9) NOT NULL AUTO_INCREMENT,
  `topicId` varchar(45) NOT NULL,
  `title` text NOT NULL,
  `details` text,
  `dayPosted` varchar(45) DEFAULT NULL,
  `username` varchar(45) DEFAULT NULL,
  `userImage` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=64 DEFAULT CHARSET=utf8;

cmets 表:

CREATE TABLE `comments` (
  `commentId` int(11) NOT NULL,
  `topicId` varchar(45) NOT NULL,
  `comments` text,
  `commentDate` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`commentId`),
  KEY `topicId_idx` (`topicId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

topicId 列在两个表中都很常见,我想在两个表之间创建关系。问题是 topicId 不是主键(我可以让它唯一)

或者我是否创建第三个表,如 topics_comments 并同时拥有:

  1. topicId 作为与 topicId 的外键关系 级联更新和删除
  2. commentId 作为与 cmets 中的 commentId 的外键关系 级联更新和删除

实际情况是我有一个博客发布网站,用户将在该博客上发表评论,其中每个博客主题都有一个topicId,每个用户评论都有一个commentId,现在我已经根据条件创建了表格:

  1. 每个博客主题可以有多个 cmets
  2. 删除博客主题后,该博客主题上的所有 cmets 必须 被删除
  3. 发布 cmets 的用户以后可以删除或编辑它们

我正在使用带有 spring bootspring jpa

的 mysql

实体类:

@Entity
@Table(name = "topics")
public class TopicBean implements Serializable {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(name = "topicId")
    private String topicId;
    @Column(name = "title")
    private String title;
    @Column(name = "details")
    private String details;
    @Column(name = "username")
    private String username;
    @Column(name = "userImage")
    private String userImage;
    @Column(name = "dayPosted")
    private String dayPosted;

//Getters and setters
}

【问题讨论】:

    标签: java mysql spring spring-boot spring-data-jpa


    【解决方案1】:

    您可以坚持使用当前架构,并且仍然能够使用 JPA 定义工作映射。这是在本地环境中对我有用的设置(这里只介绍重要的部分):

    主题

    @Entity
    @Table(name = "topics")
    public class Topic implements Serializable {
    
        @Id
        @Column(name = "id")
        private Integer id;
    
        @Column(name = "topicId")
        private Integer topicId;
    
        @OneToMany(mappedBy = "topic", cascade = {CascadeType.REMOVE, CascadeType.MERGE})
        private List<Comment> comments;
    

    评论

    @Entity
    @Table(name = "comments")
    public class Comment implements Serializable{
    
        @Id
        @Column(name = "commentId")
        private Integer commentId;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "topicId", referencedColumnName = "topicId")
        private Topic topic;
    

    记得在 TOPICS.topicsId 上添加唯一索引。

    关于链接表场景,如果你真的有,我会使用它:

    • 您的架构设计似乎是明确的单向主题,其中主题有 cmets,而评论只有一个拥有主题。所以这将是一个逻辑缺陷。
    • 如果您要从 cmets 查询并加入主题,则需要额外的加入,这可能会降低性能
    • 使用 JPA 获取评论的主题会有点尴尬,因为您将获取主题列表,然后您需要显式获取第一个条目。
    • 您最终会在主题表中得到过时/冗余的 topicId 列。

    当然,你可以正确加入,即使用主键,所以决定权在你。以下是映射:

    主题

    @Entity
    @Table(name = "topics")
    public class Topic implements Serializable {
    
        @Id
        @Column(name = "id")
        private Integer id;
    
         @ManyToMany
         @JoinTable(name="COMMON",
            joinColumns=@JoinColumn(name="TOPIC_ID"),
            inverseJoinColumns=@JoinColumn(name="COMMENT_ID"))
        private List<Comment> comments;
    

    评论

    @Entity
    @Table(name = "comments")
    public class Comment implements Serializable{
    
        @Id
        @Column(name = "commentId")
        private Integer commentId;
    
        @ManyToMany
         @JoinTable(name="COMMON",
            joinColumns=@JoinColumn(name="COMMENT_ID"),
            inverseJoinColumns=@JoinColumn(name="TOPIC_ID"))
        private Topic topic;
    

    【讨论】:

    • 如果您想使用我的一些想法来使用链接表策略,请添加信息。希望有帮助
    • 非常感谢。我很困惑是使用 JPA @join 注释还是在 mysql 中创建表之间的关系。
    • 两者都是可行的。不过,我个人会保留您当前的模式,并使用选项 1 进行映射。但是,嘿,决定是您的
    • @OneToMany(mappedBy = "topic", cascade = {CascadeType.REMOVE, CascadeType.MERGE}) private List&lt;Comment&gt; comments; 这是否意味着一个主题可以有多个 cmets 或相反?
    • 我在comments 表中有comments 列,但不在topics 表中。所以我会把注释改成这个?? @ManyToMany @JoinTable(name="topics", joinColumns=@JoinColumn(name="COMMENT_ID"), inverseJoinColumns=@JoinColumn(name="TOPIC_ID")) @Column(name = "comments") private String comments;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 2023-03-29
    • 2021-08-27
    • 2020-01-01
    • 2019-09-17
    相关资源
    最近更新 更多