Reputation: 155
I have two Classes, Fount and Criterions, the first one is one to many and the other many to one. When i call delete i get the error mentioned in the title.
I tried a lot of solutions here in stackoverflow and other sites about the same problem, but i can't do it right, i'll be glad if someone find out
Solutions i tried:
Cascade - as you can see, i'm already using the annotation, and i tried a lot of different annotations that i found in the internet
Remove the object Criterion from the object Fount and then the Fount from the Criterion before deleting the Criterion from the database
Remove from Fount object and updating the database right after it
The error:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (
mydb
.fount_criterion
, CONSTRAINTFK5p3wsropwaokyta6cmy3edvcv
FOREIGN KEY (criterions_id
) REFERENCEScriterion
(id
))
my classes Fount and Criterion:
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;
}
}
Criterion:
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;
}
}
Upvotes: 0
Views: 322
Reputation: 1832
You need to synchronize both end of the bidirectional association.
If you have only 1 bidirectional association (in your example - Criterion-Fount and Fount-Criterion), the following helper methods (for disassociating the parent from all child entities) would solve the problem:
public void addCriterion(Criterion criterion) {
criterions.add(comment);
criterion.setFount(this);
}
public void removeCriterion(Criterion criterion) {
criterions.remove(criterion);
criterion.setFount(null);
}
And make sure you're using cascading:
@OneToMany(mappedBy = "fount", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Criterion> criterions;
Upvotes: 1