Reputation: 924
I have 2 EJB 3 Entity Beans:
@Entity
public class Organisation
{
@Id
@Column(length = 64)
private String guid;
private String name;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
@JoinColumn(name = "home_unit_fk", nullable = true)
private Unit homeUnit;
}
@Entity
public class Unit
{
@Id
@Column(length = 64)
private String guid;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "organisation_fk", nullable = false)
private Organisation organisation;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_unit_fk", nullable = true)
private Unit parentUnit;
@OneToMany(mappedBy = "parentUnit", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
@OrderBy("shortName")
@OptimisticLock(excluded = true)
private Set<Unit> childUnits;
}
If I do a delete on the Organisation using standard Dao :
public int deleteByGuid(final String guid)
{
final Query query = entityManager.createQuery("delete from " + getPersistentClass().getName() + " where guid = :guid");
query.setParameter("guid", guid);
return query.executeUpdate();
}
But I get the following exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (config
.unit
, CONSTRAINT FK27D184F5D4393D
FOREIGN KEY (organisation_fk
) REFERENCES organisation
(guid
))
I don't get it. What am I doing wrong? Shouldn't JPA/Hibernate perform deletes on both the Unit and the Organisation within the same transaction?
Upvotes: 1
Views: 2752
Reputation: 326
A bulk delete query does not load objects into memory and it bypasses any cascade specified on associations.
I would code your delete method as:
public int deleteByGuid(final String guid){
Organization org = entityManager.find(Organization.class, guid);
entityManager.remove(org);
}
If you use a Query to do bulk updates, the operation is delegated to the database directly. If you wish to delete child objects, you have to set a DELETE CASCADE trigger at the "database" level.
By loading the object and removing it, Hibernate will trigger the cascade at the "object" level.
More info available at: http://twasink.net/blog/2005/04/differences-in-behaviour-between-hibernate-delete-queries-and-the-old-way/
Upvotes: 2