当前位置: 首页 > 知识库问答 >
问题:

JPA删除失败(完整性约束冲突:外键无操作)-数据模型太复杂?

元景天
2023-03-14

我遇到了一个问题,我的头脑不清醒。我真的希望有人能帮忙。

因为我的数据模型代表编程对象,所以这可能会得到一些元数据。我有三个实体:程序、Clazz和方法。类可以有多个方法,并且偶尔会继承一些其他方法(从其他类继承)。

@Entity
public class Program {

    @OneToMany(mappedBy="program", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @OrderBy("name ASC")
    private Set<Clazz> clazzes = new TreeSet<Clazz>();
}

@Entity
public class Clazz {

    @ManyToOne
    private Program program;

    @OneToMany(mappedBy="clazz", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @OrderBy("name ASC")
    private Set<Method> methods = new TreeSet<Method>();

    @ManyToMany(fetch=FetchType.LAZY, mappedBy="inheritedBy")
    @OrderBy("name ASC")
    private Set<Method> inheritedMethods = new TreeSet<Method>();

    @PreRemove
    private void tearDown() {
        inheritedMethods.clear();
    }

}

@Entity @Table(name="sf_method")
public class Method {

    @ManyToOne(html" target="_blank">optional=true)
    private Clazz clazz;

    @ManyToMany(fetch=FetchType.LAZY)
    @JoinTable(name = "sf_method_inherited_by_class", 
        joinColumns = { @JoinColumn(name = "sf_method_inherited_by_class") }, 
        inverseJoinColumns = { @JoinColumn(name = "sf_class_inherits_method") }
    )
    private Set<Clazz> inheritedBy = new HashSet<Clazz>();

    @PreRemove
    public void tearDown() {
        inheritedBy.clear();
    }

}

我需要做的是删除一个程序,包括它所有的类和方法。我使用Spring-JPA存储库,所以我的代码是:

@Autowired ProgramRepository programs;

@Transactional(readOnly=false)
public void forceDelete(Program p) {
    Set<Clazz> myClasses = p.getClazzes();
    for (Clazz c : myClasses) {
        logger.info("Clazz " + c.getName());
        for (Method m : c.getMethods()) {
            m.setClazz(null);
            methods.save(m);
        }
    }
    programs.delete(p);
}

删除代码仅在某些情况下有效。有时我会出现以下错误。

SqlExceptionHelper-完整性约束冲突:外键没有动作;FKIBMDD2FV8TNJAF4VJTOEICS73表:SF_METHODAbstractBatchImpl-HHH000010:在批发布时,它仍然包含JDBC语句

有什么想法吗?我花了这么多时间在这件事上,每次尝试解决问题都失败了。我做错了什么?

共有1个答案

养淇
2023-03-14

在这里,您试图删除父级,而不删除具有引用父级的外键的子级。

在这里,在删除p之前,您必须删除p的子对象。您可以通过以下方式获得:p.getClazzes();

同样,在删除Clazz之前,您必须删除它的孩子(在本例中,方法),如上所述...

 类似资料: