Reputation: 2114
I've hit a problem when using Hibernate to delete a JPA entity that has a @OneToMany
relationship with a child entity, but the same code works fine when using EclipseLink instead of Hibernate as the JPA provider. The annotation on the parent entity is @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)
When using Hibernate it attempts to set the join column on the child entity to null which fails as the column does not allow nulls. When using EclipseLink it deletes the child entities first and then deletes the parent entity which is the desired behaviour.
My questions are:
orphanRemoval
and CascaseType.REMOVE
features in JPA2 should function that same with both providers.I've found several similar questions on SO, however most of them either relate to JPA 1.0, using depreciated Hibernate annotations or suggest setting orphanRemoval=true
on the @OneToMany
annotation.
The version of Hibernate I'm using is 4.3.10.Final and the version of EclipseLink is 2.5.2.
To demonstrate the problem I've created the following relatively simple example.
The code for the parent entity is as follows:
@Entity
@Table(name="HOUSE")
public class HouseEntity {
@Id
@Column(name="HOUSE_ID")
private int houseId;
@Column(name="HOUSE_NAME")
private String houseName;
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)
@JoinColumn(name = "HOUSE_ID", referencedColumnName = "HOUSE_ID")
private List<RoomEntity> rooms;
//Getters, setters, equals, and hashCode omitted
}
The code for the child entity is as follows:
@Entity
@Table(name="ROOM")
public class RoomEntity {
@Id
@Column(name="ROOM_ID")
private int roomId;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "HOUSE_ID", referencedColumnName = "HOUSE_ID")
private HouseEntity house;
@Column(name="ROOM_NAME")
private String roomName;
//Getters, setters, equals, and hashCode omitted
}
The EJB code used to delete the parent entity is as follows:
@Stateless
public class HouseService {
@PersistenceContext
private EntityManager em;
public void deleteHouse(int houseId) {
HouseEntity houseEntity = em.find(HouseEntity.class, houseId);
em.remove(houseEntity);
}
}
In Hibernate the following SQL statement is executed against the database
update ROOM set HOUSE_ID=null where HOUSE_ID=?
which fails with a ORA-01407: cannot update ("TEST"."ROOM"."HOUSE_ID") to NULL
In EclipseLink the SQL statement DELETE FROM ROOM WHERE (HOUSE_ID = ?)
is executed first and then the SQL statement DELETE FROM HOUSE WHERE (HOUSE_ID = ?)
is executed.
Upvotes: 3
Views: 6172
Reputation: 5420
Try the following
@Entity
@Table(name="HOUSE")
public class HouseEntity {
@Id
@Column(name="HOUSE_ID")
private int houseId;
@Column(name="HOUSE_NAME")
private String houseName;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "house", cascade = CascadeType.ALL)
private List<RoomEntity> rooms;
//Getters, setters, equals, and hashCode omitted
}
@Entity
@Table(name="ROOM")
public class RoomEntity {
@Id
@Column(name="ROOM_ID")
private int roomId;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "HOUSE_ID", referencedColumnName = "HOUSE_ID", nullable = false)
private HouseEntity house;
@Column(name="ROOM_NAME")
private String roomName;
//Getters, setters, equals, and hashCode omitted
}
Upvotes: 1