如何自动删除连接表中的行以避免 ConstraintViolationException?

发布于 2024-09-24 01:35:48 字数 2028 浏览 2 评论 0原文

这看起来应该是一个非常简单的问题,或者至少有一个简单的答案。但是 - 我真的不是一个数据库专家,而且我在 Hibernate 学习曲线上还远远落后。也就是说,设置如下:

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

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

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;
    }
}

BarDTO.java:

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

    ...
}

在 TSQL 端,连接表的设置如下:

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 因为我没有首先删除连接表中的行(废话)。

问题:

  • 当我删除 Bar 时,我可以让 Hibernate 自动删除连接表中的行吗?如何?
  • 如果没有,我如何选择具有特定 Bar 的所有 Foo,以便我可以从每个相关 中删除该 Bar Foo 的一组 Bar

关于后一个问题,我认为这可以通过 NamedQuery 或使用 Criteria API 来完成,但我不知道具体如何编写这样的查询或应用哪些约束。我认为命名查询看起来像这样:

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

但我不确定 barId 参数会去哪里,或者如何加入 FooBar 表,因为我不知道不要将其声明为实体。 (旁注,我还记得以前尝试加入命名查询时遇到的问题 - 加入命名查询不可能吗?)

This seems like it should be a pretty simple question, or at least have a simple answer. But - I'm really not a database guy, and I'm still pretty far down on the Hibernate learning curve. That said, here's the setup:

Consider a unidirectional many-to-many relationship between two entities, from Foo to Bar:

(pardon any typos below, the following is obviously a simplification of the actual code)

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;
    }
}

BarDTO.java:

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

    ...
}

On the TSQL side, the join table is set up like this:

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

If I try to outright delete a BarDTO, I get a ConstraintViolationException because I haven't first deleted the row in the join table (duh).

Questions:

  • Can I get Hibernate to drop the rows in the join table automagically, when I delete a Bar? How?
  • If not, how do I select all the Foos that have a particular Bar, so I can remove that Bar from each relevant Foo's set of Bars?

With regard to the latter question, I think this could be done with either a NamedQuery or using the Criteria API, but I don't know specifically how to write such a query or which constraints to apply. I think it would a named query would look something like:

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

but I'm not sure where the barId parameter would go, or how to join on the FooBar table since I don't declare it as an entity. (Side note, I also recall previous issues with trying to join in a named query - is joining in a named query impossible?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

偏闹i 2024-10-01 01:35:48

当我删除 Bar 时,我可以让 Hibernate 自动删除连接表中的行吗?怎么办?

您需要从 FooDTO 中包含其引用的集合中删除 BarDTO 实例。

如果没有,我如何选择所有具有特定 Bar 的 Foo,以便我可以从每个相关 Foo 的 Bar 集中删除该 Bar?

以下应该可行:

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

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

Can I get Hibernate to drop the rows in the join table automagically, when I delete a Bar? How?

You need to remove the BarDTO instance from the collections in FooDTO that holds a reference on it.

If not, how do I select all the Foos that have a particular Bar, so I can remove that Bar from each relevant Foo's set of Bars?

The following should work:

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

Or you could make the association bidirectional and simply call bar.getFoos().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文