9

I'm having a hard time removing childs from a OneToMany-association. My entities:

@Entity
@Table(name = "PERSON")
public class PersonEntity extends BaseVersionEntity<Long> implements Comparable<PersonEntity>
{
  ...
  // bi-directional many-to-one association to Project
  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "person", orphanRemoval = true)
  private final Set<ProjectEntity> projects = new HashSet<ProjectEntity>();
  ...

@Entity
@Table(name = "PROJECT")
public class ProjectEntity extends BaseVersionEntity<ProjectPK>
{
  @EmbeddedId
  private ProjectPK id;
  ...
  // bi-directional many-to-one association to UdbPerson
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "PERSON_ID", nullable = false, insertable = false, updatable = false)
  private PersonEntity person;
  ...

@Embeddable
public class ProjectPK implements Serializable
{
  // default serial version id, required for serializable classes.
  private static final long serialVersionUID = 1L;

  @NotNull
  @Column(name = "PERSON_ID")
  private Long personId;
  ...

My unsuccessful attempt to delete the childs:

personEntity.getProjects().clear();

This works, but I don't think thats the right approach:

for (Iterator<ProjectEntity> iterator = personEntity.getProjects().iterator(); iterator.hasNext();)
{
  ProjectEntity projectEntity = iterator.next();
  projectDao.deleteEntity(projectEntity);
  iterator.remove();
}

What am I doing wrong here?

Thanks
Jonny

user871611
  • 3,307
  • 7
  • 51
  • 73

1 Answers1

16

The association is bidirectional, and the owning side of a bidirectional association is the one where there is no mappedBy attribute. This means that in this case, the owning side is the project side.

Hibernate only considers the owning side to know if the association exists or not. This means that to break the association between a person and a project, you must set the person to null in the project.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks JB Nizet, this did the trick. Here the code: `for (Iterator iterator = personEntity.getProjects().iterator(); iterator.hasNext();) { ProjectEntity projectEntity = iterator.next(); projectEntity.setPerson(null); iterator.remove(); }` – user871611 May 03 '12 at 08:40
  • What if person can not be null? – Igor G. Dec 17 '13 at 15:17
  • @IgorG. If person can't be null, then it makes no sense to remove the association. – JB Nizet Dec 17 '13 at 15:57
  • 4
    This answer is incorrect. The real answer you're looking for (and allows you to keep your not-null constraint) can be found here: http://stackoverflow.com/questions/3068817/hibernate-triggering-constraint-violations-using-orphanremoval – JamesD Mar 31 '14 at 16:49
  • @JamesD: the answer you linked to says exactly the same thing as mine. *you need to add a mappedBy attribute to declare the owning side of the association* and `contact.setAccount(null);`. – JB Nizet Mar 31 '14 at 16:56
  • @JB. First off, if you follow the other answer, you do NOT need to null out that association. Secondly, you told Igor that he cannot make the person not-null.....but that's incorrect. You CAN, if you follow the other answer. This answer is confusing and there's no need to set the account to null at all. – JamesD Apr 01 '14 at 03:18
  • @JamesD: What don't you understand in "you need to manage both sides of the link [...]: contact.setAccount(null);"? And second, that's not what I said. What I said is that he couldn't make it not null if he wanted to leave persons in the database without any associated project: "If person can't be null, then it makes no sense to remove the association." Removing the person is not the same thing as removing the association between a project and a person. – JB Nizet Apr 01 '14 at 05:51
  • I also have a similar problem, but I have `null` on the `Person` in `Project` but still, I ain't able to remove. I am also having `mappedBy` in `Person` side. – JavaTechnical Oct 04 '14 at 18:06
  • hello sir, I'm using `Session#saveOrUpdate` hibernate specific, In DB I've **3 children**, and from view I've **2 children** to be updated and want to remove **3rd or last one**, How to deal with that situation? Should I use `Session#get()` or `Session#load()`, to know which element to remove before update? – Shantaram Tupe Feb 26 '18 at 10:04
  • @JB Nizet +1 for memotechnic aid of resolving owning side of bidirectional relationship – Andrew Sneck Aug 18 '21 at 14:03