Search code examples
javajpaeclipselink

Why does JPA mark objects as dirty even if the values did not change?


I'm working on an application which sometimes calls setters on JPA managed entities. Why does JPA mark these objects as dirty even if the values didn't change?

For example I have an object, which has a child object. I can call entity.setMyChild(entity.getMyChild()) and JPA still apparently treats the entity as dirty and will update it.


Solution

  • You would need to talk to the people who wrote the specifications (and implementations) for a definitive answer, but I can think of a couple of plausible reasons.

    • How do you determine that the old and new values did not change?

      • You could call equals(Object) (for object types)! But is it "sound" to use equals for this? What about fields that don't contribute to equality buts still need to be persisted?

      • You could use object identity. But what if the application creates "equal" instances willy-nilly?

      In short, it is difficult to come up with a suitable definition of "changed value".

    • What about the cost? For "set to dirty only if changed" to work, you need to compare the old and new values on each set call. Assuming that we used equals(Object). Consider that the set call could be made many times, and that the equals(Object) call could be expensive, we potentially have a serious performance problem.

    I suspect that they would have considered this kind of thing, and decided that the simpler "set means dirty" model would be easier to use.

    Anyway, if you don't like the way JPA works in this case, you can always add another setter method in your persistent object's API that only calls the JPA setter when the new value is different ... according to some model.