JPA implementation patterns: Removing entities

Vincent Partington

For the last few weeks I have been covering the implementation patterns I discovered while writing JPA applications. The last two blogs covered saving entities and retrieving entities. But when you're really through with your entities, I guess you'd want to remove them too. ;-) So that is the subject of this blog.

Just like retrieving an entity, removing an entity is pretty simple. In fact it's all you need to do is pass the entity to the EntityManager.remove method to remove the entity from the database when the transaction is committed (Of course you'd actually invoke a remove method on your DAO which in turn invokes EntityManager.remote). That's all there is to it. Usually. Because when you're using associations (be they bidirectional or not) things get more interesting.

Removing entities that are part of an association

Consider the example with the Order and OrderLine classes we've discussed previously. Let's say we want to remove and OrderLine from an Order and we go about it in this simple manner:

orderLineDao.remove(lineToDelete);

There is a problem with this code. When you tell the entity manager to remove the entity, it will not automatically be removed from any associations that point to it. Just like JPA does not automatically manage bidirectional associations. In this case that would be the orderLines set in the Order object pointed to by the OrderLine.order property. If I were to word this statement as a failing JUnit test case, it would be this one:

OrderLine orderLineToRemove = orderLineDao.findById(someOrderLineId);
Order parentOrder = orderLineToRemove.getOrder();
int sizeBeforeRemoval = parentOrder.getOrderLines().size();
orderLineDao.remove(orderLineToRemove);
assertEquals(sizeBeforeRemoval - 1, parentOrder.getOrderLines().size());

Implications

The failure of this test case has two subtle and therefore nasty implications:

  • Any code that uses the Order object after we have removed the OrderLine but will still see that removed OrderLine. Only after committing the transaction, starting a new transaction, and reloading the Order in a new transaction, it will not show up in the Order.orderLines set anymore. In simple scenarios we won't run into this problem, but when things get more complex we can be surprised by these "zombie" OrderLines appearing.
  • When the PERSIST operation is cascaded from the Order class to the Order.orderLines association and the containing Order object is not removed in the same transaction, we will receive an error such as "deleted entity passed to persist". Different from the "detached entity passed to persist" error we talked about in a previous blog, this error is caused by the fact that the Order object has a reference to an already deleted OrderLine object. That reference is then discovered when the JPA provider flushes the entities in the persistence context to the database, causing it try and persist the already deleted entity. And hence the error appears.

The simple solution

To remedy this problem, we also have to remove the OrderLine from the Order.orderLines set. That sounds awfully familiar... In fact, when managing bidirectional associations we also had to make sure both sides of the association were in a consistent state. And that means we can reuse the pattern we used there. By adding an invocation of orderLineToRemove.setOrder(null); to the test it will succeed:

OrderLine orderLineToRemove = orderLineDao.findById(someOrderLineId);
Order parentOrder = orderLineToRemove.getOrder();
int sizeBeforeRemoval = parentOrder.getOrderLines().size();
orderLineToRemove.setOrder(null);
orderLineDao.remove(orderLineToRemove);
assertEquals(sizeBeforeRemoval - 1, parentOrder.getOrderLines().size());

The pattern

But doing it like this makes our code brittle as it depends on the users of our domain objects to invoke the right methods. The DAO should be responsible for this. A very nice way to solve this problem is to use the @PreRemove entity lifecycle hook like this:

@Entity
public class OrderLine {
	[...]

	@PreRemove
	public void preRemove() {
		setOrder(null);
	}
}

Now we can just invoke OrderLineDao.remove() to get rid of an unwanted OrderLine object.

Originally this blog suggested introducing a HasPreRemove interface with a preRemove method that would be invoked by the DAO. But Sakuraba commented below that the @PreRemove annotation is just the thing we need here. Thanks again, Sakuraba!

Removing orphans

But what, you ask, would happen if we were to just remove the OrderLine from the Order.orderLines set like so:

Order parentOrder = orderLineToRemove.getOrder();
parentOrder.removeOrderLine(orderLineToRemove);

?

The OrderLine would indeed be removed from the Order.orderLines set. And not just in this transaction. If we retrieve the Order object again in a new transaction, the removed OrderLine still would not show up. But if we were to look in the database, we would see that the OrderLine is still there. It just has its OrderLine.order field set to null. What we are seeing here is an "orphaned" set element. There are two ways to solve this problem:

While the second solution is vendor-specific it does have the nice feature of not requiring your code to invoke a DAO remove method every time you remove an entity from a set. But to make it obvious you are using a vendor specific extension, you should refer to those annotations using the full package name (as Java Persistence with Hibernate suggests too):

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Set orderLines = new HashSet();

Please note that CascadeType.ALL does not include the DELETE_ORPHAN cascade type. That's why the example here explicitly sets it.

So we can conclude that removing entities is simple unless you are dealing with associations. In that case you need to take extra precautions to make sure the entity is removed from any objects referring to it and from the database at the same time. See you at the next blog! In the meantime, please drop any remarks in the comment section below.

P.S. If you will be attending J-Spring next week, come and join my talk about this subject from 14:25 until 15:15 (it'll be in Dutch though). Or find me somewhere at the conference to talk about JPA. I'll probably be hovering around the Xebia booth. :-)

For a list of all the JPA implementation pattern blogs, please refer to the JPA implementation patterns wrap-up.

Comments (23)

  1. a - Reply

    April 9, 2009 at 9:33 pm

    How about PreRemovable for the name of the interface?

  2. Sakuraba - Reply

    April 11, 2009 at 10:14 am

    Why not use an Entity Lifecyle aware method within the OrderLine class?

    @PreRemove
    public void preRemove() {
    setOrder(null);
    }

    This way you dont have to modidy your generic DAO, or am I wrong here?

    • mac - Reply

      February 27, 2013 at 9:05 am

      What if the commit still fails for some other reason? The remove will be rolled back but the association in your in-memory entity is still removed. What is the best pattern to "rollback" the preremove?

  3. Vincent Partington - Reply

    April 14, 2009 at 9:03 am

    @Sakuraba: You are very right! Using the @PreRemove annotation keeps the DAO simpler. And it solves the problem of what to name that interface. ;-)

    I will update the example later today. Thx again for learning me a new trick. That's what I hoped for when starting these blogs.

  4. Andrew Phillips - Reply

    April 15, 2009 at 8:45 am

    But if we were to look in the database, we would see that the OrderLine is still there. It just has its OrderLine.order field set to null.

    In a relational DB, would the mapping between OrderLine and Order not usually be implemented using a foreign key, ORDER_ID or suchlike?
    If the schema has a foreign key constraint reflecting this, it should not be possible to get orphaned OrderLines - you should instead get a NOT NULL constraint violation.

    Setting aside the broader discussion of the merits and drawbacks of foreign keys, in this case they could help to enforce your business model semantics.

  5. ed - Reply

    April 16, 2009 at 9:15 am

    He Vincent,

    Ik was gisteren bij je JSpring 2009 voordracht.
    Hastikke goed gedaan, lekker rustig en duidelijk. Alleen het eind was een beetje rommelig, maar dat komt vast nog een keer goed ;).

    Anyway: ik vond het prettig om herkenbare problement te zien, maar had wel het gevoel alsof ik 5 jaar terug in tijd gng. Ik had gehoopt meer innovatieve oplossingen te zien.
    Een paar dingetjes (zeker niet compleet):

    - Inject je Dao in je domein objecten (met Spring bijvoorbeeld). Je gebruikt het Anemic Domain pattern wat echt not-done is met de huidige technieken en tijd. Stop gewoon je remove, save, etc... operaties direct in je domain objecten (ik vroeg hier ook naar tijdens je voordracht). Zie: http://www.theserverside.com/news/thread.tss?thread_id=38047

    - Waarom je eigen DTO converter schrijven als er tools als Dozer zijn die dit reeds netjes voor je doen?

    - Waarom niet dingen van JPA 2.0 reeds in je voordracht gebruiken?

    - Ik zou die DAO implementaties niet laten exenden van je DAO base class waarin je get/find, etc... methods zitten maar ik zou deze laatste als een Persister class injecten in je DAO implementatie class. Dit werkt prettiger (ik had het eerste exact zoals jij het schetste) en scheelt een inherance, en je weet dat die zeldzaam zijn want je heb er maar 1 (dus: gebruik delegator pattern).

    - Ik weet niet precies of JPA dat nu goed ondersteund, maar maak ook meer gebruikt van de hibernate load/get i.p.v. alles via de get laten lopen.
    Voorbeeld: als je een nieuw adres aanmaakt en deze persist, en stop daarin een Country object waarvan je zeker weet dat hij bestaat in de db, gebruik dan load voor het country object. Dit scheelt een query en bij grote loads, kan dat een behoorlijke performance boost zijn.

    - Je refereerde naar de bekende Bijbel van Gavin King en Christian. Dan ben je op de hoogte van Entity en ValueType objecten waar ze steeds onderscheid in maken.
    Samengevat: Entity object: heeft eigen levenscyclus en ValueType object niet en die hangt altijd aan een Entity object.
    Voorbeeld:
    Entity -> Member object.
    ValueType -> Email object.
    Member heeft eigen methods zoals remove/save, etc... en Email niet, die volgt het gedrag van zijn Member (als Component in HIbernate termen).
    Dit werkt bijzonder prettig en ik heb hier op diverse grote enterprise projecten goede ervaringen mee. D.w.z.: Categoriseer al je domain ojbecten in deze 2 (m.u.v. een mix voor performance redenen maar dat is een technisch feesie).

    - Ik mis een flexible DoaSearch interface (naast de DAO interface). Voorbeeld van 1 van zijn methods:
    public List findEntities(J persistenceClass, SearchCriteria search, SortCriteria sort)

    Zoals je ziet kan je hiermee felxibel queries bouwen (SQL, HQL of JPA achtig afhankelijk van je implementatie die je inschiet).
    Dit werkt er prettig omdat je hiermee in het Criteria object aangeeft op welke velden je van een Member wil zoeken en vervolgens maakt de query builder automatisch via een specifieke Query appender (via het observer pattern) de query voor je en klaar is kees. Deze appenders schiet je in via Spring, en het toevoegen van een find is dus puur configuratie in de backend, het schrijven de de nieuwe appender en criteria.

    Euuwwww.. dit was het wel even, de rest ben ik alweer vergeten.

    Misschien heb je er wat aan (ik wilde je eigenlijk paar dingetjes mailen, maar het zijn er toch meer geworden :( )....
    Als je wat wil weten, hoor ik het wel.
    Cheers,
    Ed
    PS: vergeet voortaan je water niet :)

  6. ed - Reply

    April 16, 2009 at 9:46 am

    BTW: wat me nog te binnen schoot net (mijn schermpie staat nog open).
    Als je je Entity laat extenden van een gemeenschappelijkde EntityBase class, kan je daar allerlei handige functionaliteit in stoppen zoals:
    - Visitor pattern (gebaseerd op reflectie). Dit heb je nodig als je correct met proxies om wil gaan.
    - Validators met Error return object via Observer pattern.
    - Observer pattern die listeners afvuurt voor/na save, remove etc... Dit werkt erg prettig en kan je gebruiken om bijvoorbeeld een datum te updaten voordat het de db in gaat, etc...

    Nog wat: Pas op met protected methods in Domain objecten. Je zei op ten duur in je presentatie dat je die setInternal* method protected kon maken. DIT KAN NIET als je wilt dat je proxies (met lazy loading) goed werken. Dan moet dit nl public zijn om je proxies correct te triggeren. Dus pas hier mee op.
    Maar goed: proxies in domain objecten is ook een heel apart onderwerp waardoor vaak vele bugs in projecten zitten omdat het niet correct wordt begrepen.
    Bijvoorbeeld: het gebruik van instanceof en getClass() method in equals() van domain object is uit ten boze en kan tot raare fouten leiden. Zie de bijbel voor meer uitleg.
    Ik zelf heb altijd standaard testen die ik op domain objecten los laat om te testen of ze proxy-safe zijn.

    Ik ga weer snel verder....
    -- Ed

  7. Vincent Partington - Reply

    April 19, 2009 at 3:35 pm

    @Andrew: Yes, the relation between OrderLine and Order will be mapped by a foreign key. But no, a constraint is not added by default. One way to signal these orphans when they occur is to add set optional=false on the relation from OrderLine to Order:

    @ManyToOne(optional=false)
    private Order order;
    

    If you do that, Hibernate will throw this exception when you try and commit the transaction in which you created that orphan:
    org.hibernate.PropertyValueException: not-null property references a null or transient value: com.xebia.jpaip.order.OrderLine.order

  8. Vincent Partington - Reply

    April 19, 2009 at 4:23 pm

    @Ed: Thanks for attending my J-Spring 2009 talk. I'll remember to bring my own water next time. ;-)

    I'm not going to translate your questions, but as this blog is usually in English, I will reply to your questions in English. If you don't mind.

    1. When starting out with JPA, I started using more of the modern ideas, doing away with DAO's and DTO's, etc. Only to discover that these abstractions do have a place in the architecture. But I would love to hear other peoples' innovations on JPA.

    2. Acually, I don't think injecting your DAO into your domain objects is a good idea. They are in fact two different things: a domain object represents one, euh, thing in your domain, while a DAO represents a collection of those things. So I think having a non-static findOrder method in OrderDao is nicer than having a static findOrder in the Order class. The single responsibility principle applies here, I think.
    But if a domain object needs access to other services, injecting them with those other services is very needed to prevent your domain model from being anemic. In fact that is what we do in our application. Most of our logic is in our domain objects; the services only load the right objects by invoking the DAO and then invoke the right methods on those objects. This is something I will revisit in a later blog.

    3 I have looked at Dozer and it looks very nice. The only reason we haven't used it yet, is because the code we had to write to copy properties from DO to DTO and back was not that much. Introducing another framework for this did not seem like something that would pay off. The whole team would have to know about the framework, we could run into bugs in that framework, etc.

    4. I didn't mention any JPA 2.0 features because I have no real-life experience with them. Once I do, I will probably be writing a few more blogs. I'm really interested to see how the Criteria thing works out.

    5. Using delegation instead of implementation inheritance is the thing to do these days. Then again, these DAO's are so small that I feel that implementation inheritance is simpler to understand. See also my comment dated April 19th, 2009 at 3:50 pm on my DAO blog.

    6. AFAIK, JPA doesn't have something similar to Session.load so that is opportunity for performance you don't get with JPA.

    7. Yup, we also use ValueType objects, a.k.a. embedded objects, where ever we can. They make life a lot easier: no DAO to write, no lifecycle to worry about.

    8. Actually, I think having a very flexibly DAO search interface makes the code harder to read. I'd rather have a number of specific finder methods for all the different ways my app needs to find entities. Then again, if your app needs to provide ad-hoc search capabilities to the end user, such an interface might be very beneficial.

    9. (from your second comment) I'm not really sure what you mean here. Could you give an example? Having all entities extend from a base class seem a bit EJB2-ish to me. It would also "waste an inheritace", something you object to when it comes to DAOs.

    10. Hmm, the package scope methods (I did not mentiond protected methods) in our code does work. I've also heard about problems with using field access (my preference) versus property access when it comes to Hibernate proxies. I have a feeling that the proxies created for JPA work slightly differently than those created for Hibernate. The fact that JPA by default eagerly loads to-one associations probably helps here too. This is something I am going to investigate for my next blog on lazy loading.

    Thanks again for attending. And for your long reply! Regards, Vincent.

  9. allan - Reply

    August 11, 2009 at 7:46 am

    Shouldn't that be @PostRemove rather than @PreRemove, what if things go wrong during deleting?

  10. Vincent Partington - Reply

    August 19, 2009 at 7:44 am

    @allan: Putting the logic to disassociate this object from any it is connected to makes sure you won't run into any constraint violation in the database when removing it, so that is good reason to put it in @PreRemove.

    That does mean that the Java object model will be inconsistent with the contents of the database when the deletion fails. Then again, in that case an exception will probably be thrown ending the user request/transaction anyway.

  11. [...] Removing entities [...]

  12. Colin - Reply

    November 1, 2009 at 11:32 am

    There is a error:
    org.apache.cxf.interceptor.Fault: Removing a detached instance ...OrderLine

    when I executed the orderLineDao.remove(...)

  13. Vincent Partington - Reply

    November 6, 2009 at 8:27 am

    @Colin: Have you set your transaction boundaries correctly? The error message implies that the session has been closed before you invoked orderLineDao.remove().

  14. JPA Implementation Patterns | Upthrust - Reply

    February 2, 2010 at 5:42 pm

    [...] Removing Entities [...]

  15. Patrick - Reply

    March 26, 2010 at 4:08 pm

    Hi,

    I use cascade = CascadeType.REMOVE on the parent entity. In the DB I have a not null contraint on the foreign key in addition to a foreign key constraint. With this setup removing a Parent entity fails because the JPA layer (Hibernate in my case) tries to set a null value for the foreign key prior to deleting this child entity. Does this mean that I can't use this not null constraint on the child entity foreign key? Is there a way to for JPA to simply delete the child entities without seting a null value first?

    - Patrick

  16. Ondrej Medek - Reply

    April 12, 2010 at 2:12 pm

    Hibernate links are broken.

  17. Dimitris Tsitses - Reply

    July 29, 2010 at 6:44 am

    Hi guys, I believe JPA 2.0 now supports the "orphanRemoval=true" attribute in the @xxxToMany annotation, adding it seems to take care of the problem automatically without requiring Hibernate dependencies.

    Dimitris

  18. Mattias - Reply

    September 10, 2010 at 8:29 am

    I'm a bit confused, shouldn't the preRemove be:

    @Entity
    public class OrderLine {
    	[...]
     
    	@PreRemove
    	public void preRemove() {
    		getOrder().getOrderLines().remove(this);
    	}
    }
    

    ?

    Thank you for your articles.

    /Mattias

  19. Vincent Partington - Reply

    September 10, 2010 at 4:04 pm

    @Mattias: If you refer back to the post on bidirectional associations, you'll see that that won't work. The set returned by getOrderLines() is an unmodifiable set. You'll also see that invoking setOrder(null) will do exactly what you want: remove this OrderLine from the set in the parent Order.

  20. Nanda - Reply

    February 10, 2011 at 8:13 am

    Hi. I dont think this blog is valid with CASCADE types available in JPA 1.0 itself for any directional associations? Am I missing something?

    • Johannes Leimer - Reply

      September 20, 2011 at 2:45 pm

      Hi,
      thank you for your excellent articles about using JPA!

      I have used your statements in a project but I found some issues with the usage of the @PreRemove method, which is not spec-compliant with the JPA 2.0 specification.

      The JPA 2.0 spec [http://download.oracle.com/auth/otn-pub/jcp/persistence-2.0-fr-oth-JSpec/persistence-2_0-final-spec.pdf] says:
      "In general, the lifecycle method of a portable application should not invoke EntityManager or Query operations, access other entity instances, [b]or modify relationships within the same persistence context.[43] A lifecycle callback method may modify the non-relationship state of the entity on which it is invoked.

      [43] The semantics of such operations may be standardized in a future release of this specification"

      So I contacted a JPA architect and he answered
      "You are still responsible to maintain the relationships, just not via the @PreRemove callback [...] A common practice is to provide helper methods on the Entity class to help maintain the relationships. Probably not as 'slick' as your @PreRemove solution, but it would be a spec-compliant solution."

      So I think the deletion of an entity has do be done by JPA _and_ the normal business logic. So It would be - using your code - something like this.

      em.getTransaction().begin();
      orderline.preRemove();
      em.remove(orderline);
      em.getTransaction().commit();

  21. Menelaos Perdikeas - Reply

    October 30, 2012 at 4:02 pm

    Note that the @PreRemove hook in the child entity can lead to a concurrent modification exception when you remove an instance of the father entity from a collection using EntityManager::remove. I have a demo which demonstrates that in JPA/Hibernate. Removing the @PreRemove hook fixes it. I can send you the whole demo if you like, or just the code / trace. I ended up removing the @PreRemove hook and delete father entities works fine but I am not sure yet what are the ramifications in the correctness of your pattern because of this change.

Add a Comment