2

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.

Freiheit
  • 8,408
  • 6
  • 59
  • 101
  • Maybe the JPA provider only see the setter invocation (using bytecode manipulated interceptors) not the actual value. – Jin Kwon Jul 01 '13 at 17:39
  • Forget about JPA, if you were to manage that yourself then how would you guarantee that the value actually didn't change in regards to the value in the database, considering that the same setter can be invoked multiple times? – Bhesh Gurung Jul 01 '13 at 17:49
  • This is *not* in the JPA spec; some JPA providers (e.g DataNucleus JPA) certainly do not mark such a field as "dirty" under that situation. So it is vendor-specific, and there are many ways things can be done (see Stephen C answer) – DataNucleus Jul 01 '13 at 18:46

2 Answers2

5

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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

EclipseLink does not perform an update if nothing changed. What is the update SQL being generated? Did you change the id of the child object, or do you have two copies of the object?

Please include all of your code and SQL log.

James
  • 17,965
  • 11
  • 91
  • 146