What does mean Hibernate's "unsaved-value mapping was incorrect"?

Pavel Vlasov picture Pavel Vlasov · Jul 18, 2014 · Viewed 15.2k times · Source

There is a famous exception:

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [my.Entity#123456]

This is a very familiar situation when "row was updated or deleted by another transaction".

But what means another possibility - "unsaved-value mapping was incorrect"? And how to reproduce such situation intentionally?

Grails 2.2.0

Answer

For a description of unsaved-value see http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#mapping-declaration-id:

unsaved-value (optional - defaults to a "sensible" value): an identifier property value that indicates an instance is newly instantiated (unsaved), distinguishing it from detached instances that were saved or loaded in a previous session.

Hibernate needs this in rare cases, when saveOrUpdate() is not able to determine if the entity is new or detached.

If an entity is determined by means of your unsaved-value as detached, but is instead new, then hibernate can't compare the version numbers (because the entity just doesn't exist in the database). But Hibernate can't know if your unsaved-value mapping is not correct or the entity has been deleted in another transaction. This is described in org.hibernate.StaleStateException as well:

Thrown when a version number or timestamp check failed, indicating that the Session contained stale data (when using long transactions with versioning). Also occurs if we try delete or update a row that does not exist.