代码之家  ›  专栏  ›  技术社区  ›  Matt Ball

如何自动删除联接表中的行以避免ConstraintIOlationException?

  •  3
  • Matt Ball  · 技术社区  · 15 年前

    这似乎是一个非常简单的问题,或者至少有一个简单的答案。但是-我真的不是一个数据库员,而且我仍然在休眠学习曲线上走得很远。也就是说,设置如下:

    考虑两个实体之间的单向多对多关系,从 Foo Bar :

    (请原谅下面的任何拼写错误,下面显然是对实际代码的简化)

    foodto.java:

    @Entity
    @Table(name = "MyDB.dbo.Foo")
    class FooDTO implements Serializable
    {
        private int id;
        private String name;
        private Set<BarDTO> bars = new HashSet<BarDTO>();
    
        ...
    
        @Fetch(FetchMode.JOIN)
        @ManyToMany(fetch = FetchType.EAGER)
        @JoinTable(name = "MyDB.dbo.FooBar",
                   joinColumns = { @JoinColumn(name = "fooId") },
                   inverseJoinColumns = { @JoinColumn(name = "barId") })
        public Set<BarDTO> getBars()
        {
            return bars;
        }
        public void setBars(Set<Bar> bars)
        {
            this.bars = bars;
        }
    }
    

    java版本:

    @Entity
    @Table(name = "MyDB.dbo.Bar")
    class BarDTO implements Serializable
    {
        private int id;
        private String name;
    
        ...
    }
    

    在TSQL端,join表的设置如下:

    CREATE TABLE [dbo].[FooBar](
        [id] [int] NOT NULL IDENTITY PRIMARY KEY,
        [fooId] [int] NOT NULL,
        [barId] [int] NOT NULL,
        CONSTRAINT fk_FooBar_FooId FOREIGN KEY (fooId) REFERENCES [dbo].[Foo](id),
        CONSTRAINT fk_FooBar_BarId FOREIGN KEY (barId) REFERENCES [dbo].[Bar](id),
    ) ON [PRIMARY]
    END
    

    如果我试图直接删除 BarDTO ,我得到一个 ConstraintViolationException 因为我没有首先删除联接表中的行(duh)。

    问题:

    • 当我删除一个 酒吧 ?怎么用?
    • 如果没有,如何选择所有 有一个特别的 酒吧 ,这样我就可以去掉那个 酒吧 从每个相关 的集合 酒吧 S?

    关于后一个问题,我 认为 这可以通过 NamedQuery 或者使用标准API,但是我不知道具体如何编写这样的查询或者应用哪些约束。我认为命名查询应该类似于:

    SELECT f FROM FooDTO f INNER JOIN ??? WHERE f.id = ???
    

    但我不确定 barId 参数将转到,或如何在 FooBar 表,因为我没有将其声明为实体。(旁注,我还记得以前尝试加入命名查询的问题——加入命名查询不可能吗?)

    1 回复  |  直到 15 年前
        1
  •  2
  •   Pascal Thivent    15 年前

    当我删除一个栏时,是否可以让Hibernate自动删除联接表中的行?怎么用?

    你需要移除 BarDTO 集合中的实例 FooDTO 上面有一个参考。

    如果没有,如何选择所有具有特定栏的foo,以便从每个相关foo的栏集合中删除该栏?

    以下内容应该有效:

    SELECT f FROM FooDTO f WHERE :bar MEMBER OF f.bars 
    

    或者您可以使关联双向,并简单地调用 bar.getFoos() .