简体   繁体   中英

How do I delete a row in a join table automatically, to avoid a ConstraintViolationException?

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 Foo s that have a particular Bar , so I can remove that Bar from each relevant Foo 's set of Bar s?

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?)

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() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM