1
votes

I can't get the cascase remove to work in a Java EE container managed application, using the Hibernate JPA implmentation. Help would be appreciated. I have an entity 'Company', with four OneToMany relations to other entities. When testing the application (using the Arquillian framwork), I cannot get the cascade delete working; The company entity gets removed, the child entities are still present after the deletion. I've read here: JPA and Hibernate Cascade DELETE OneToMany does not work that this might be a test issue, so as I've read every post on this subject here and tried every possibilty, I'm now thinking it might have something to do with the Arquillian testing framework and the classes that are (not) being loaded in the test deployment.

My company entity looks like this:

public class CompanyEntity implements Serializable {

  private static final long serialVersionUID = 2L;
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  @NotNull
  private String name;
  @NotNull
  private String companyCode;
  @OneToMany(targetEntity = ContactInfoEntity.class, cascade =   CascadeType.REMOVE, orphanRemoval = true)
  private List<ContactInfoEntity> contactInfo;
  @OneToMany(targetEntity = AddressEntity.class,cascade = CascadeType.REMOVE, orphanRemoval = true)
  private List<AddressEntity> addresses;
  @OneToMany(targetEntity = ConnectionInfoEntity.class,cascade = CascadeType.REMOVE, orphanRemoval = true)
  private List<ConnectionInfoEntity> connectionInformation;
  @OneToMany(targetEntity = PreferenceEntity.class,cascade = CascadeType.REMOVE, orphanRemoval = true)
  private List<CompanyPreferenceEntity> preferences;
}

And my entities are all defined in this way:

public class AddressEntity implements Serializable {
  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  @NotNull
  @Size(min = 2)
  private String country;
  @NotNull
  @Size(min = 2)
  private String city;
  private String zipCode;
  private String street;
  private boolean isPrimaryAddress;
}

The delete function does the following:

  • Merge the company to be deleted
  • get the lists
  • 'find' each element in the list in a for loop (EntityManager.find), and removes it (I've tried 'merge' too, doesn't work)
  • set each of the lists to null (don't know if it is necessary, but it was mentioned in some posts)
  • remove the company entity

Thanks in advance!

2
Why are you removing each element in the lists? If you are using cascade delete, you dont need to remove them.. Removing the parent entity will remove the children.viniciusjssouza
Right. I was getting desperate.Arno

2 Answers

1
votes

This turned out to be my own fault, by implementing my test in the wrong way. Let me explain what I did to test:

  • Added a company (persisted to database)
  • Added contact info, addresses, ... (persisted to database)
  • Added those to the company object
  • Forgot to update the company entity, so the addresses, contact info, ... were linked to the company at runtime, but these changes were not persisted
  • Deleted the company and expected contacts and addresses, ... to be cascade deleted, which did not happen because I forgot to update.
0
votes

You need to provide the @JoinColumn annotation to indicate the owner of the relationship:

@OneToMany(targetEntity = ContactInfoEntity.class, cascade =   
  CascadeType.REMOVE, orphanRemoval = true)
@JoinColumn(name="company_id")
private List<ContactInfoEntity> contactInfo;

More info about this kind of mapping is available here: https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Unidirectional_OneToMany,_No_Inverse_ManyToOne,_No_Join_Table_(JPA_2.x_ONLY)