4

I have an issue with the orphan removal in JPA 2. Inside a transaction I create the target object of one-to-one relation (OrderDirectDebit) then add it to an existing and persistent DonationIntent (using merge method). Then I remove the relation by nullifying it. Then I persist again (using merge method again).

I have orphanRemoval configured for the relation but still the object is not removed. The spec says that the remove operation is applied when flush operation is called ( which should occur as soon as the transaction ends). But in my example the orphaned entity is still there after commit. When I call flush manually after the merge operation (inside my custom persist method), the orphaned entity gets removed. If I call the flush operation manually on a different entity manager that uses the same persistence context (from an interceptor), the orphaned entity does not get removed.

I can't make any sense of the behaviour. Do I have to call to flush manually directly after the merge? Does that make any sense? Please comment. Here are my class definitions, the persist method of the repository and the unit test code:

    // this is a method of a stateless bean with transaction required
    // it is run inside an arquillian unit test
    public void testOrderCreation() {
    DonationIntent donation = repositoryDonationIntent.findById(id);
    Country country = testhelper.getCountryGermany();
    BankAccount bankAccount =testhelper.getBankAccountForTestPerson1();
    Assert.assertFalse(donation.createOrderDirectDebit(23.0d, country, OrderType.EState.NEW, bankAccount).hasErrors());
    donation = repositoryDonationIntent.persist(donation);
    Assert.assertNotNull(donation.getOrder());
    donation.setOrder(null);
    donation = repositoryDonationIntent.persist(donation);
    Assert.assertTrue(repositoryDonationIntent.findById(donation.getId()) == donation);
    Assert.assertNull(repositoryDonationIntent.findById(donation.getId()).getOrder());
    //the assert verifies the the relation of the object in the persistence context is null,still after commit it does not remove it
    }

The entity model:

    @Entity
    public class DonationIntent extends AutoIdDomainObject implements IAggregateRoot<Long> {

    @OneToOne(cascade = CascadeType.ALL, optional = true, orphanRemoval = true)
    private OrderType order; // this is the relation that does not get orphaned
    }

    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    public abstract class OrderType extends AutoIdDomainObject {

    // some more attributes and relations here

    }


    @Entity
    public class OrderDirectDebit extends OrderType {

     // some more attributes and relations here
    }

The persist method of the repository:

    @Override
public <D extends IDomainObject<?>> D persist(Class<D> domainClass, D domainObject)      {
    //TODO Do not permit old revisions of versioned objects to be persisted
    if (domainObject == null)
        return null;
    // invalid domain objects may not be persisted
    if (!domainObject.isValid()) {
        DomainObjectErrorLogger.log(domainObject.getErrors());
        return domainObject;
    }

    // check if update or insert
    if (isPersistent(domainClass, domainObject)) {
        domainObject = em.merge(domainObject);
        em.flush(); // a call to flush here will remove orphaned entity
    } else {
        em.persist(domainObject);

    }

    return domainObject;
}
bennidi
  • 2,092
  • 21
  • 27
  • See http://stackoverflow.com/questions/7510388/jpa-2-0-hibernate-and-orphanremoval-just-replacing-an-entity-does-not-remov – axtavt Jan 06 '12 at 10:42
  • Thanks, but this scenario does not apply to my case as described above. I do not set a new value until transaction commit – bennidi Jan 06 '12 at 15:05
  • Did you ever figure out this issue? I'm having something similar (with a `@OneToMany` mapping) in which the offending row is not deleted (see http://stackoverflow.com/q/24579374/827480). – Eric B. Jul 04 '14 at 19:21
  • I don't remember exactly but I think it was a Hibernate issue and we found a workaround. It's been a while. Sorry for not posting back, when we resolved the issue. You might check if changing persistence provider helps. Another problem we had with unorphaned objects was related to bidirectional mappings (which are not handled very well by any provider I know). Sidenote: I think bidirectional mappings should not be used at all. You should rather design access path unidirectional and use queries to retrieve from the other side. – bennidi Jul 04 '14 at 21:33

0 Answers0