2012-02-10 159 views
2

我想在我的“标记”实体之间建立关系。的关系是双向的,并存储在我的实体“TagRelation”:JPA - 独特的双向实体关系

enter image description here

每个标签的关系应该只有在tag_relations表1项,由于关系的方向是没有意义的。例如,如果我插入:

“森林”(标签1)< - > “树”(标签2)

我应该不可能插入关系的其他方式:

“树”(标签1)< - > “森林”(标签2)

这是表tag_relation的SQL代码:

CREATE TABLE IF NOT EXISTS `tag_relation` (
    id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT , 
    `tag_id_1` INT(10) UNSIGNED NOT NULL , 
    `tag_id_2` INT(10) UNSIGNED NOT NULL , 
    `type` ENUM('related_subject','synonymous','alternative_writing') NOT NULL , 
    PRIMARY KEY (`id`) , 
    INDEX `fk_tag_1` (`tag_id_1` ASC) , 
    INDEX `fk_tag_2` (`tag_id_2` ASC) , 
    UNIQUE INDEX `ux_relation_1_2` (`tag_id_1` ASC, `tag_id_2` ASC) , 
    UNIQUE INDEX `ux_relation_2_1` (`tag_id_2` ASC, `tag_id_1` ASC) , 
    CONSTRAINT `fk_tag_1` 
     FOREIGN KEY (`tag_id_1`) 
     REFERENCES `mm`.`tag` (`id`) 
     ON DELETE NO ACTION 
     ON UPDATE NO ACTION, 
    CONSTRAINT `fk_tag_2` 
     FOREIGN KEY (`tag_id_2`) 
     REFERENCES `mm`.`tag` (`id`) 
     ON DELETE NO ACTION 
     ON UPDATE NO ACTION) 
ENGINE = InnoDB 
AUTO_INCREMENT = 1 

唯一索引,因为他们现在不执行我想要的独特关系。我如何在我的数据库中执行此操作?

+1

我不是专家,所以可能会有更好的解决方案。但是,如果您认为[tag1,tag2]等于[tag2,tag1],则可以强制执行这条规则,即情侣总是在第一列中插入最低ID,在第二列中插入最大ID。这可以通过一个简单的检查约束来实现。 – 2012-02-10 16:05:40

+0

你是指触发器?解决方案听起来不错。我必须找出如何编写该触发器。 – BigJ 2012-02-10 17:11:20

+0

我不认为它是有效的,因为TagRelation实体已经设置了tag_1和tag_2引用。您建议的触发器可能会在插入数据库时​​将其转向,导致TagRelation实体和数据库之间不一致。但也许我可以做一个触发器来检查数据库中是否存在唯一的关系。 – BigJ 2012-02-10 17:18:17

回答

0

关系类型在运行时是否动态?如果不是我想你会得到更好的直接在标签放置的关系:

public class Tag{ 
    @OneToOne private Tag related_subject; 
    @OneToOne private Tag synonymous; 
    @OneToOne private Tag alternative_writing; 
    //setters and getters 
} 

这会让你的关系,更安全和更高性能。

+0

我实际上实施了JB Nizet的解决方案,工作正常。我不确定我是否了解您的解决方案。它必须有可能有多个相同类型的关系,但我猜你的解决方案中的标签关系可以更改为列表。但在这种情况下,JPA将创建3个连接表。然后,我自己创建一个tag_relation会更容易。 – BigJ 2012-11-20 15:50:07