3

How do you get a OneToOne item to automatically remove with JPA/Hibernate? I would expect simply setting the OneToOne item to be null in the class that contains would be smart enough to allow Hibernate to delete it.

Given a simple object, simplified:

@Entity
public class Container {
    private Item item;

    @OneToOne(cascade=CascadeType.ALL)
    public Item getItem() { return item; }

    public void setItem(Item newItem) { item = newItem; }
}

When an Item is set on Container an Container is persisted with merge a row gets inserted.

Container container = new Container();
container.setItem(new Item());
container = entityManager.merge(container);
// Row count is 1

But when the item is set null, or to another item, the old object still exists in the table.

container.setItem(null);
container = entityManager.merge(container);
// Row count is STILL 1, leaving orphaned rows.

So, how do I remove these OneToOne orphans?

Sheldon
  • 391
  • 3
  • 7
  • Have you found a solution to this? – kosoant Apr 29 '09 at 07:31
  • I am using a partial solution: If Car contains Driver then I put an @CascadeType(cascade=CasadeType.ALL) on car.driver so the driver goes away when the car does, then I avoid replacing the Driver object when possible. – Sheldon May 01 '09 at 21:11

4 Answers4

1

I'm guessing that the reasone behind hibernate not allowing DELETE_ORPHAN to OneToOne relations is related to this issue.

If you really want this bad, you can hack your way with these steps:

  • transform your OneToOne relation into a OneToMany:
  • add a method just to get the first element of the child's collection (this is optional but handy)
  • use the DELETE_ORPHAN annotation

Of course, this is a big hack.

Miguel Ping
  • 18,082
  • 23
  • 88
  • 136
1

As JPA 2.0 has been released for a very long time now, you could simply use:

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
Jacob van Lingen
  • 8,989
  • 7
  • 48
  • 78
0

Try to change to

@OneToOne
@Cascade(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN})

See also my answer on similar post here.

Community
  • 1
  • 1
FoxyBOA
  • 5,788
  • 8
  • 48
  • 82
  • Works fine, thank you. I am okay with using Hibernate-specific annotations until JPA 2.0. – Sheldon Apr 02 '09 at 16:22
  • Ignore that, updated test reveals the approach above does *not* work. According to Hibernate team member Emmanuel delete-orphan is not supposed to work with OneToOne http://forum.hibernate.org/viewtopic.php?p=2287278 – Sheldon Apr 02 '09 at 16:32
0

Unfortunately, there is no way to do this in JPA without tying yourself to Hibernate's implementation.

So yes, as Foxy says, you can use org.hibernate.annotations.CascadeType instead of the standard JPA annotation, which allows you to specify DELETE_ORPHAN. If you want to use the JPA abstraction, you must delete orphans yourself as of yet.

Henning
  • 16,063
  • 3
  • 51
  • 65