MySQL-三个实体之间的多对多关系

时间:2020-04-10 15:09:14

标签: mysql database-design spring-data-jpa foreign-keys many-to-many

我在为数据库中的多对多关系找出最佳设计时遇到了麻烦。我的项目允许用户创建我们所谓的日志警报。日志警报将检查给定日志是否满足某些条件,如果满足,它将向AWS SNS主题发送消息。我要做的是将日志警报与AWS SNS主题相关。我还想将分配该日志警报的用户与该AWS SNS主题相关联。

我有一个表类XRefUserLogAlarmSNSTopic。它具有三个外键。该表的目的是将哪些SNS主题与哪些日志警报相关联,并指示哪个用户进行了关联。这对我来说似乎很混乱,当我尝试在Spring JPA中创建新的日志警报或联接表时遇到各种错误。我的问题是,对于我想要实现的目标,是否有更好的数据库结构

    UserId INT NOT NULL AUTO_INCREMENT,
    Username VARCHAR(50) NOT NULL,
    Password TEXT NOT NULL,
    Email VARCHAR(255) NOT NULL,
    Dashboard LONGTEXT NOT NULL,
    PRIMARY KEY (UserId),
    UNIQUE (Username),
    UNIQUE (Email)
);

CREATE TABLE SNSTopics (
    SNSTopicId INT NOT NULL AUTO_INCREMENT,
    TopicName VARCHAR(50) NOT NULL,
    TopicArn VARCHAR(255) NOT NULL,
    PRIMARY KEY (SNSTopicId),
    UNIQUE (TopicName),
    UNIQUE (TopicArn)
);

CREATE TABLE LogGroups (
    LogGroupId INT NOT NULL AUTO_INCREMENT,
    Name VARCHAR(255) NOT NULL,
    PRIMARY KEY (LogGroupId),
    UNIQUE (Name)
);

CREATE TABLE Keywords (
    KeywordId INT NOT NULL AUTO_INCREMENT,
    Word VARCHAR(70),
    PRIMARY KEY (KeywordId),
    UNIQUE (Word)
);

CREATE TABLE LogAlarms (
    LogAlarmId INT NOT NULL AUTO_INCREMENT,
    LogLevel VARCHAR(5) NOT NULL CHECK (LogLevel IN ('TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR')),
    Comparison VARCHAR(2) CHECK (Comparison IN ('==', '<', '<=', '>', '>=')),
    AlarmName VARCHAR(255) NOT NULL,
    KeywordRelationship CHAR(3) CHECK (KeywordRelationship IN ('ANY', 'ALL', NULL)),
    PRIMARY KEY (LogAlarmId),
    UNIQUE (AlarmName)
);

CREATE TABLE MetricAlarms (
    MetricAlarmId INT NOT NULL AUTO_INCREMENT,
    AlarmArn VARCHAR(100) NOT NULL,
    PRIMARY KEY (MetricAlarmId),
    UNIQUE (AlarmArn)
);

CREATE TABLE XRefUserMetricAlarm (
    UserMetricAlarmId INT NOT NULL AUTO_INCREMENT,
    UserId INT NOT NULL,
    MetricAlarmId INT NOT NULL,
    PRIMARY KEY (UserMetricAlarmId),
    FOREIGN KEY (UserId) REFERENCES Users(UserId) ON DELETE CASCADE,
    FOREIGN KEY (MetricAlarmId) REFERENCES MetricAlarms(MetricAlarmId) ON DELETE CASCADE,
    UNIQUE (UserId, MetricAlarmId)
);

CREATE TABLE XRefLogAlarmLogGroup (
    LogAlarmLogGroupId INT NOT NULL AUTO_INCREMENT,
    LogAlarmId INT NOT NULL,
    LogGroupId INT NOT NULL,
    PRIMARY KEY (LogAlarmLogGroupId),
    FOREIGN KEY (LogAlarmId) REFERENCES LogAlarms(LogAlarmId) ON DELETE CASCADE,
    FOREIGN KEY (LogGroupId) REFERENCES LogGroups(LogGroupId) ON DELETE CASCADE,
    UNIQUE (LogAlarmId, LogGroupId)
);

CREATE TABLE XRefLogAlarmKeyword (
    LogAlarmKeywordId INT NOT NULL AUTO_INCREMENT,
    LogAlarmId INT NOT NULL,
    KeywordId INT NOT NULL, 
    PRIMARY KEY (LogAlarmKeywordId),
    FOREIGN KEY (LogAlarmId) REFERENCES LogAlarms(LogAlarmId) ON DELETE CASCADE,
    FOREIGN KEY (KeywordId) REFERENCES Keywords(KeywordId) ON DELETE CASCADE,
    UNIQUE (LogAlarmId, KeywordId)
);

CREATE TABLE XRefUserLogAlarmSNSTopic (
    UserLogAlarmSNSTopicId INT NOT NULL AUTO_INCREMENT,
    LogAlarmId INT NOT NULL,
    SNSTopicId INT NOT NULL,
    UserId INT NOT NULL,
    PRIMARY KEY (UserLogAlarmSNSTopicId),
    FOREIGN KEY (LogAlarmId) REFERENCES LogAlarms(LogAlarmId) ON DELETE CASCADE,
    FOREIGN KEY (SNSTopicId) REFERENCES SNSTopics(SNSTopicId) ON DELETE CASCADE,
    FOREIGN KEY (UserId) REFERENCES Users(UserId) ON DELETE CASCADE,
    UNIQUE (LogAlarmId, SNSTopicId, UserId)
);```

1 个答案:

答案 0 :(得分:0)

为匹配您的描述,您的XRefUserLogAlarmSNSTopic不正确。

您实际上并不想链接三个实体,而只是链接两个:您想将日志警报与AWS SNS主题相关联(这是标识该关系的两个值),然后添加一个用户作为对该关系的属性。尽管在这种情况下,该特定属性是指另一个实体,但从逻辑上讲,它与例如存储该关系创建时间(由该用户创建)的时间戳。

当前表的区别在于主键/唯一键:您的当前表允许您在警报和主题之间多次添加关系(如果不同的用户添加它们,因为仅需(alarm, topic, user)唯一,而不是(alarm, topic)是唯一的,而user是该关系的属性。

我还会考虑是否要在ON DELETE CASCADE列中使用UserId。虽然级联LogAlarmIdSNSTopicId是有意义的,但是当删除创建关系的用户时,并不需要删除所有关系(尽管这当然取决于您的要求)并不明显。最好将它们设置为null。所以我建议一个像

的表
CREATE TABLE XRefLogAlarmSNSTopic (   -- user not part of table name
    LogAlarmSNSTopicId INT NOT NULL AUTO_INCREMENT,  
    LogAlarmId INT NOT NULL,
    SNSTopicId INT NOT NULL,
    UserId INT NULL,  -- null
    PRIMARY KEY (UserLogAlarmSNSTopicId),
    FOREIGN KEY (LogAlarmId) REFERENCES LogAlarms(LogAlarmId) ON DELETE CASCADE,
    FOREIGN KEY (SNSTopicId) REFERENCES SNSTopics(SNSTopicId) ON DELETE CASCADE,
    FOREIGN KEY (UserId) REFERENCES Users(UserId) ON DELETE SET NULL,  -- set null
    UNIQUE (LogAlarmId, SNSTopicId)  -- user not part of primary key candidate
)

显然,您想要这种三向关系,例如每个用户都会创建他们自己的 alarm-topic-relations,在这种情况下,您的表是正确的,只是您的描述不够准确。

相关问题