Ich habe 2 Entitäten, die Geofence und Device sind, sobald der Benutzer einen Geofence zu einem Gerät zuweisen, wird eine Verknüpfung erstellt von GeofenceDevice Entity dargestellt.Hibernate ConstraintViolationException on delete
Das Problem ist, dass wenn ich ein GeofenceDevice Objekt löschen, möchte ich eine Fehlermeldung erhalten:
Cannot delete or update a parent row: a foreign key constraint fails (`db_gpstracking`.`tj_geofence_device_gdev`, CONSTRAINT `FKE085AA815DC5054A` FOREIGN KEY (`GDEV_GEOFENCE_ID`) REFERENCES `t_geofence_geo` (`GEO_ID`))
Hier ist mein Code:
Geräteeinheit
package com.sifast.gpstracking.model;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
import com.sifast.gpstracking.utils.TypeEnum;
@NamedQueries({ @NamedQuery(name = "findDeviceByUniqueId", query = "from Device d where d.uniqueId = :uniqueId") })
@Entity
@Table(name = "T_DEVICE_DEV")
public class Device implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "DEV_ID", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "DEV_NAME", length = 1024, nullable = false)
private String name;
@Column(name = "DEV_UNIQUE_ID", nullable = false, unique = true)
private String uniqueId;
// TODO Add column last modification and date insert in every table
@Column(name = "DEV_LAST_UPDATE", nullable = true)
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdate;
@Column(name = "DEV_PROTOCOL", length = 1024, nullable = true)
private String protocol;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "device")
private List<Position> listPosition;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)
@JoinColumn(name = "DEV_USER_ID", referencedColumnName = "USR_USER_ID", nullable = false)
private User user;
@Enumerated(EnumType.STRING)
@Column(name = "DEV_TYPE", nullable = false)
private TypeEnum type;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "device")
private List<GeofenceDevice> listGeofenceDevice;
public Device() {
super();
// TODO Auto-generated constructor stub
}
public Device(String name, String uniqueId, Date lastUpdate, String protocol) {
this.name = name;
this.uniqueId = uniqueId;
this.lastUpdate = lastUpdate;
this.protocol = protocol;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUniqueId() {
return uniqueId;
}
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
public Date getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public List<Position> getListPosition() {
return listPosition;
}
public void setListPosition(List<Position> listPosition) {
this.listPosition = listPosition;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public TypeEnum getType() {
return type;
}
public void setType(TypeEnum type) {
this.type = type;
}
public List<GeofenceDevice> getListGeofenceDevice() {
return listGeofenceDevice;
}
public void setListGeofenceDevice(List<GeofenceDevice> listGeofenceDevice) {
this.listGeofenceDevice = listGeofenceDevice;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id^(id >>> 32));
result = prime * result + ((uniqueId == null) ? 0 : uniqueId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Device other = (Device) obj;
if (id != other.id)
return false;
if (uniqueId == null) {
if (other.uniqueId != null)
return false;
} else if (!uniqueId.equals(other.uniqueId))
return false;
return true;
}
@Override
public String toString() {
return name;
}
// @PrePersist
// private void updateCreationDate() {
// //creationDate = ...
// }
//
// @PreUpdate
// private void updateModificationDate() {
// //creationDate = ...
// }
}
Gefence Einheit
GeofenceDevice Einheit
package com.sifast.gpstracking.model;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
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.Query;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
@NamedQueries({
@NamedQuery(name = "findGeofenceDeviceByGeofenceIdAndDeviceId", query = "from GeofenceDevice geoDev where geoDev.device = :device and geoDev.geofence = :geofence"),
@NamedQuery(name = "findAllGeofenceDeviceByGeofenceId", query = "from GeofenceDevice geoDev where geoDev.geofence = :geofence") })
@Entity
@Table(name = "TJ_GEOFENCE_DEVICE_GDEV")
public class GeofenceDevice implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "GDEV_ID", nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "GDEV_GEOFENCE_ID", referencedColumnName = "GEO_ID", nullable = false)
private Geofence geofence;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "GDEV_DEVICE_ID", referencedColumnName = "DEV_ID", nullable = false)
private Device device;
// si status == true alors la geofencing correspond à ce device est activé sinon il est désactivé
@Column(name = "GDEV_STATUS", nullable = true)
private boolean status;
// si inside == true alors c'est alerte d'entrée sinon c'est une alerte de sortie de la zone
@Column(name = "GDEV_ALERT_TYPE", nullable = true)
private boolean inside;
public GeofenceDevice() {
super();
// TODO Auto-generated constructor stub
}
public GeofenceDevice(Geofence geofence, Device device, boolean status, boolean inside) {
this.geofence = geofence;
this.device = device;
this.status = status;
this.inside = inside;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Geofence getGeofence() {
return geofence;
}
public void setGeofence(Geofence geofence) {
this.geofence = geofence;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public boolean isInside() {
return inside;
}
public void setInside(boolean inside) {
this.inside = inside;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((device == null) ? 0 : device.hashCode());
result = prime * result + ((geofence == null) ? 0 : geofence.hashCode());
result = prime * result + (inside ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GeofenceDevice other = (GeofenceDevice) obj;
if (device == null) {
if (other.device != null)
return false;
} else if (!device.equals(other.device))
return false;
if (geofence == null) {
if (other.geofence != null)
return false;
} else if (!geofence.equals(other.geofence))
return false;
if (inside != other.inside)
return false;
return true;
}
@Override
public String toString() {
return "GeofenceDevice [geofence=" + geofence + ", device=" + device + "]";
}
}
Und hier ist ein Link für die Logs
Dank @Franck, die Lösung für das Problem war die Verwendung von 'orphanRemoval'. Ich poste es in einer Antwort, die du sehen kannst;) –