首页 > 解决方案 > 使用休眠删除mysql中的行:无法删除或更新父行

问题描述

我有两个类,Font 和 Criterions,第一个是一对多,另一个是多对一。当我调用 delete 时,我得到了标题中提到的错误。

我在stackoverflow和其他网站上尝试了很多关于相同问题的解决方案,但我做错了,如果有人发现我会很高兴

我尝试过的解决方案:

Cascade - 正如你所看到的,我已经在使用注释,并且我尝试了很多我在互联网上找到的不同注释

从对象 Fount 中删除对象 Criterion,然后从 Criterion 中删除 Fount,然后再从数据库中删除 Criterion

从 Fount 对象中删除并在它之后立即更新数据库

错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:无法删除或更新父行:外键约束失败(mydb. fount_criterion,CONSTRAINT FK5p3wsropwaokyta6cmy3edvcvFOREIGN KEY(criterions_id)REFERENCES criterionid))

我的课源和标准:

package br.com.engcon.entities;

import javax.persistence.*;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "fount")
//@SequenceGenerator(name="SEQUENCE", sequenceName="fount_id_seq")
public class Fount {
    
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id; 
    
    @Column(nullable=false, name="url")
    private String url;
    
    @OneToMany(fetch = FetchType.LAZY, targetEntity = Criterion.class)
    @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE})
    private List<Criterion> criterions;
//  
//  @OneToMany(fetch = FetchType.LAZY, targetEntity = Text.class, orphanRemoval = true)
//  @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE})
//  private List<Text> texts;

    @Column(nullable=false, name="isUsed")
    private boolean isUsed = false;

    @Column(nullable=false, name="isActive")
    private boolean isActive = true;
    
    @Column(nullable=false, name="isDeleted")
    private boolean isDeleted = false;

    public Fount(String url) throws URISyntaxException {
        this.url = url;
        this.criterions = new ArrayList<Criterion>();

        new URI(url);
    }
    
    public Fount(String url, List<Criterion> criterions) {
        this.url = url;
        this.criterions = criterions != null? criterions : new ArrayList<Criterion>();
    }
    
    public Fount() {
        this.criterions = new ArrayList<Criterion>();
    }
    
    public URI getURI() {
        if(!url.isEmpty()) {
            try {
                return new URI(url);
            } catch (URISyntaxException e) {
                return null;
            }
        }
        return null;
    }
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public List<Criterion> getCriterions() {
        return criterions;
    }

    public void setCriterions(List<Criterion> criterions) {
        this.criterions = criterions;
    }

    public void setUrl(String url) {
        this.url = url;
    }
    
    public void addCriterions(List<Criterion> criterions){
        this.criterions = this.criterions != null? this.criterions : new ArrayList<Criterion>();
        
        this.criterions.addAll(criterions);
    }
    
    public void addCriterions(Fount fount) {
        this.criterions = criterions != null? criterions : new ArrayList<Criterion>();
        
        for(Criterion criterion : fount.getCriterions()) {
            Criterion newCriterion = criterion.clone();
            
            newCriterion.setFount(this);
            
            criterions.add(newCriterion);
        }
    }

    public Criterion addCriterion(Criterion criterion) {
        this.criterions = criterions != null? criterions : new ArrayList<Criterion>();

        Criterion newCriterion = criterion.clone();
        newCriterion.setFount(this);
        
        this.criterions.add(newCriterion);

        return criterion;
    }

    public Criterion addCriterion(String criterionTxt) {
        return this.addCriterion(new Criterion(criterionTxt));
    }
    
    public String getUrl() {
        return this.url;
    }
    
    @Override
    public String toString() {
        return this.getUrl();
    }

    public boolean isUsed() {
        return isUsed;
    }

    public void setUsed(boolean used) {
        isUsed = used;
    }

    public boolean isActive() {
        return isActive;
    }

    public void setActive(boolean active) {
        isActive = active;
    }

    public boolean isDeleted() {
        return isDeleted;
    }

    public void setDeleted(boolean isDeleted) {
        this.isDeleted = isDeleted;
    }
}

标准:

package br.com.engcon.entities;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

@Entity
@Table(name = "criterion")
//@SequenceGenerator(name="SEQUENCE", sequenceName="criterion_id_seq")
public class Criterion {
        
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @ManyToOne(fetch=FetchType.EAGER)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JoinColumn(name="fount_id", nullable=false)
    private Fount fount;
    
    @Column(nullable=true, name="word_filter")
    private String word;
    
    @Column(nullable=false, name="case_sensitive")
    private boolean caseSensitive;
    
    public Criterion() {
        // TODO Auto-generated constructor stub
        caseSensitive = false;
    }
    
    public Criterion(String word) {
        this.word = word;
        this.caseSensitive = false;
    }
    
    public Criterion(String word, boolean caseSensitive) {
        this.word = word;
        this.caseSensitive = caseSensitive;
    }
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getWord() {
        return word;
    }
    
    @Override
    public Criterion clone(){
        return new Criterion(this.word, this.caseSensitive);
    }
    
    public void setWord(String word) {
        this.word = word;
    }

    public boolean isCaseSensitive() {
        return caseSensitive;
    }

    public void setCaseSensitive(boolean caseSensitive) {
        this.caseSensitive = caseSensitive;
    }

    public Fount getFount() {
        return fount;
    }

    public void setFount(Fount fount) {
        this.fount = fount;
    }
    
    @Override
    public String toString() {
        return this.word;
    }
}

标签: javahibernate

解决方案


您需要同步双向关联的两端

如果您只有 1 个双向关联(在您的示例中 - Criterion-Fount 和 Fount-Criterion),则以下辅助方法(用于将父级与所有子实体解除关联)将解决该问题:

public void addCriterion(Criterion criterion) {
    criterions.add(comment);
    criterion.setFount(this);
}

public void removeCriterion(Criterion criterion) {
    criterions.remove(criterion);
    criterion.setFount(null);
}

并确保您使用的是级联:

@OneToMany(mappedBy = "fount", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Criterion> criterions;

推荐阅读