Search code examples
jpaentity

JPA Entity Manager Merge with no changes in the object


I'm trying to use Entity Manager's merge method to update an object in a database when there is no changes in the object. Say the row has the following attributes:

id             DECIMAL(11) NOT NULL,
name           CHAR(20) NOT NULL, 
lastModified   TIMESTAMP NOT NULL FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP

And say I have an object (let's call it a Person) in a database with the following attributes:

{id: 1, name: "example", lastModified: 2019-05-22 16:24:54.771}

So the lastModified attribute is something that the db updates every time there is a change on the row.

Now when I'm first fetching the object and then updating the person's name to "example" (the same value that it already has in the database), and then using using merge to update it, the lastModified attribute doesn't seem to update in the db. i.e.

Person person = em.find(Person.class, 1)
person.setName("example")
em.merge(person)

After the above actions, the lastModified is still 2019-05-22 16:24:54.771 (the same as earlier). Now if I would have changed the name i.e.

Person person = em.find(Person.class, 1)
person.setName("new name")
em.merge(person)

So now the lastModified would have updated as well.

Any help with this one? Could someone please explain me why the row doesn't update when there are no changes made to the object? :) Thanks!


Solution

  • When you use merge, Hibernate first runs a Select statement in the tuple you're trying to merge. This select is executed to get the latest state of the tuple, to then, run the update in the database, with the data that has changed in your tuple.

    As you say in your example, you haven't changed any data, as you're trying to update the name to the same as it was before, so hibernate won't run any update to the database.

    You can read more about it referring to Hibernate Dirty Checking Mechanism.

    If you really want to update this column even when no data's changed, you have to do it at the application layer, by setting it manually when saving the Person object:

    person.setLastModified(LocalDateTime.now())