Reputation: 1725
I have two tables: t_promo_program and t_promo_program_param.
They are represented by the following JPA entities:
@Entity
@Table(name = "t_promo_program")
public class PromoProgram {
@Id
@Column(name = "promo_program_id")
private Long id;
@OneToMany(cascade = {CascadeType.REMOVE})
@JoinColumn(name = "promo_program_id")
private List<PromoProgramParam> params;
}
@Entity
@Table(name = "t_promo_program_param")
public class PromoProgramParam {
@Id
@Column(name = "promo_program_param_id")
private Long id;
//@NotNull // This is a Hibernate annotation so that my test db gets created with the NOT NULL attribute, I'm not married to this annotation.
@ManyToOne
@JoinColumn(name = "PROMO_PROGRAM_ID", referencedColumnName = "promo_program_id")
private PromoProgram promoProgram;
}
When I delete a PromoProgram, Hibernate hits my database with:
update
T_PROMO_PROGRAM_PARAM
set
promo_program_id=null
where
promo_program_id=?
delete
from
t_promo_program
where
promo_program_id=?
and last_change=?
I'm at a loss for where to start looking for the source of the problem.
Upvotes: 4
Views: 4183
Reputation: 445
Double-check whether you're maintaining bidirectional association consistency. That is; make sure that all PromoProgramParam
entities that link to a PromoProgram
as its parent are also contained in said parent's params
list. It's a good idea to make sure this happens regardless of which side "initiates" the association if you will; if setPromoProgram is called on a PromoProgramParam, have the setter automatically add itself to the PromoProgram's params
list. Vice versa, when calling addPromoProgramParam on a PromoProgram, have it set itself as the param's parent.
I've encountered this problem before as well, and it was due to not maintaining bidirectional consistency. I debugged around into Hibernate and found that it was unable to cascade the delete operation to the children because they weren't in the list. However, they most certainly were present in the database, and caused FK exceptions as Hibernate tried to delete only the parent without first deleting its children (which you've likely also encountered with the @NonNull in place).
FYI, I believe the proper "EJB 3.0"-way of making the PromoProgramParam.promoProgram field (say that a 100 times) non-nullable is to set the optional=false attribute on the @ManyToOne annotation.
Upvotes: 1