I'm using Spring Data (version 1.13.9.RELEASE) and have a CrudRepository
called myRepository
. I'm calling myRepository.save(myObject)
, to overwrite an existing instance of myObject
in the database, and I'm specifying some fields of myObject
as null
.
For example:
{
"prop1": "val1",
"prop2": null,
"prop3": "val3"
}
When I call myRepository.save(myObject)
and read the return value, all of the fields of myObject
that I set as null
are returned as null
(so prop2
in this example).
However, the value for prop2
in the database is NOT null
after calling save()
- it still has the previous value before I called save()
.
This is actually the behavior that I want in this particular situation (to ignore null
values when calling myRepository.save()
), but I'd like the return value of save()
to reflect what is actually in the database after the operation, rather than only returning the updated fields and setting fields specified as null
to null
or their default value (such as false
in the case of a boolean.
Is this the expected behavior of CrudRepository
's save()
behavior?
To understand the problem you need to understand a little bit about Hibernate Object Lifecycle.
The Hibernate Object Lifecycle consist of these states : 1. Transient State 2. Persistent State 3. Detached State etc
When you create a new object, its in the transient state and Hibernate has no means of detection of objects present/created in the transient state.
When you call save()
saveOrUpdate()
then the object moves from transient state to persistent state and now Hibernate will start keeping a track of all the changes made to the object (but the object is not yet written in the db).
So in your case, since the object is not in the persistent state, hibernate fails to recognise it and will fire (most likely) an insert
query. However, if the object was already in the persistent state, hibernate would have known that some fields have modified and hence will fire an update
query.
That is why you need to make sure the object is in persistent state if you want hibernate to fire an update
query.
It means that the transaction is not complete yet and all the changes are only within the cache. To force updating you may call entityManager.flush()
or move all the logic that you need into a separate public method of another Service or Manager and annotate it as @Transactional
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.