Hibernate:在没有 CascadeType.REMOVE 的情况下删除 ManyToMany 链接

问题描述 投票:0回答:1

我有这样的数据库表:

这些是外键约束:

-- If current variable is being referenced by another variable, restrict deletion
ALTER TABLE variable_variable
    ADD CONSTRAINT variable_variable_variable_id_to_fkey
        FOREIGN KEY (variable_id_to) REFERENCES variable (id)
            ON DELETE RESTRICT;

-- If current variable reference other variable, delete its link by cascade
ALTER TABLE variable_variable
    ADD CONSTRAINT variable_variable_variable_id_from_fkey
        FOREIGN KEY (variable_id_from) REFERENCES variable (id)
            ON DELETE CASCADE;

所以,如果我有这样的参考资料:

  1. Other Variable -> Current Variable
    ,那么
    Current Variable
    就得禁止删除
  2. Current Variable -> Other Variable
    ,那么
    Current Variable
    删除也应该删除级联上从
    Current Variable
    Other Variable
    的链接(链接存储在
    variable_variable
    表中)。

这是我的

variable
表的 Hibernate 实体。

@Entity
@Table(name = "variable")
@Getter
@Setter(PROTECTED)
@NoArgsConstructor(access = PROTECTED)
@DynamicUpdate
public class Variable {
    @EmbeddedId
    private VariableId id;

    @ManyToMany(fetch = LAZY)
    @JoinTable(
        name = "variable_variable",
        joinColumns = @JoinColumn(name = "variable_id_from"),
        inverseJoinColumns = @JoinColumn(name = "variable_id_to")
    )
    private Set<Variable> variables = new HashSet<>();

    @ManyToMany(fetch = LAZY)
    @JoinTable(
        name = "variable_variable",
        joinColumns = @JoinColumn(name = "variable_id_to", updatable = false, insertable = false),
        inverseJoinColumns = @JoinColumn(name = "variable_id_from", updatable = false, insertable = false)
    )
    // this collection is readonly and never updates
    private Set<Variable> inverseVariables = new HashSet<>();
    
    ...
}

所以,

ManyToMany
关系在拥有方面,我没有
CascadeType.REMOVE
。 但是如果我调用
EntityManager.remove(variable)
,那些SQL语句被调用:

Query:["delete from variable_variable where variable_id_to=?"]
Params:[(7fbbf360-74a0-48db-a1e2-d3b1ab0a869f)]

Query:["delete from variable_variable where variable_id_from=?"]
Params:[(7fbbf360-74a0-48db-a1e2-d3b1ab0a869f)]

Query:["delete from variable where id=?"]
Params:[(7fbbf360-74a0-48db-a1e2-d3b1ab0a869f)]

Hibernate 过早地从

variable_variable
中删除链接。但是,这不是我需要的行为。它打破了我之前描述的
variable_variable
表中复杂数据库约束的整个想法。所以,我不希望 Hibernate 从那里删除任何东西。

我设法用原生查询解决了这个问题:

em.createNativeQuery("DELETE FROM variable WHERE id = :id")
            .setParameter("id", variableId)
            .executeUpdate();

无论如何,我不想介绍原生查询。是否可以告诉 Hibernate 不要删除

variable_variable
行删除
Variable

java hibernate jpa orm cascade
1个回答
0
投票

我设法用

mappedBy
逆向引用解决了这个问题。看下面的代码片段:

@Entity
@Table(name = "variable")
@Getter
@Setter(PROTECTED)
@NoArgsConstructor(access = PROTECTED)
@DynamicUpdate
public class Variable {
    @EmbeddedId
    private VariableId id;

    @ManyToMany(fetch = LAZY)
    @JoinTable(
        name = "variable_variable",
        joinColumns = @JoinColumn(name = "variable_id_from"),
        inverseJoinColumns = @JoinColumn(name = "variable_id_to")
    )
    private Set<Variable> variables = new HashSet<>();

    @ManyToMany(fetch = LAZY, mappedBy = "variables")
    // this collection is readonly and never updates
    private Set<Variable> inverseVariables = new HashSet<>();
    
    ...
}

现在当我调用

em.remove(variable)
时,生成了那些SQL语句:

Query:["delete from variable_variable where variable_id_from=?"]
Params:[(7fbbf360-74a0-48db-a1e2-d3b1ab0a869f)]

Query:["delete from variable where id=?"]
Params:[(7fbbf360-74a0-48db-a1e2-d3b1ab0a869f)]

只有

Current Variable
和引用
Current Variable -> Other Variable
被删除。如果有引用
Other Variable -> Current Variable
,则由于违反数据库完整性而导致删除失败。正是我需要的

© www.soinside.com 2019 - 2024. All rights reserved.