views:

80

answers:

2

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.

A: 

Oh crud, it was a missing "mappedBy" field in PromoProgram.

JBristow
+1  A: 

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.

voetsjoeba
Upvoted for the "optional=false" bit.
JBristow