46

I have short question:

Do I need a repo.save(x) call on @Transactional methods?

I ask cause I see changes on my DB without save, and read no clear docs about it.

So is it working as intended, or just a (welcome) unexpected behavior?

example:

@Autowired
private UserRepo repo;

@Transactional  
@PutMapping
public Long put(@RequestBody User user)
{
  User u = repo.findOne(user.getId());
  u.setName("Paul");
  repo.save(u); // DO I NEED THIS LINE?
}

I'am just unsure about it, so maybe someone can shed some light on the subject?

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
Gregor Sklorz
  • 1,645
  • 2
  • 19
  • 27
  • 3
    yes, this is normal in managed (JEE / JTA) eninvronment. Every attached object is saved – Jacek Cz Oct 12 '17 at 11:14
  • 3
    @YannicKlem persisted entities are saved by Hibernate when a transaction is flushed, so no manual `save()` is necessary. This is described in [11.5 Modifying persistent objects](http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html#objectstate-modifying). No clue if this is a feature solely within Hibernate, or if this is described within the JPA specification as well. – g00glen00b Oct 12 '17 at 11:36
  • Thank you for clarification. I was completely unaware of this behavior! – Yannic Bürgmann Oct 12 '17 at 11:50
  • Thank you :) That clears it – Gregor Sklorz Oct 12 '17 at 13:17

1 Answers1

80

If you retrieve an entity, for example using the findOne method call within a transactional method it has become managed from that point by the persistence provider.

Now if you make any changes to that entity (which is actually a proxy object), upon transaction commit, those changes will be persisted to the database, regardless of the fact of invoking the save or update methods.

save or persist has to be used when you are creating a new entity from scratch and persistence provider does not know of its existence yet.

Remember that you can prevent making any changes upon commit, if you use detach or evict methods on that particular entity before those changes occur.

SilverNak
  • 3,283
  • 4
  • 28
  • 44
Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63
  • 1
    Thank you, sounds good for me. – Gregor Sklorz Oct 12 '17 at 13:19
  • hi if i use findById, setValue(changeSomeValue) and then do save(oldObject) and then i going to delete(oldObject), but the result my save(oldObject) is not executed, the jpa only execute delete(oldObject) in the last action, but if i comment the delete line, the code is updating, can u help me? here is my question https://stackoverflow.com/questions/64331680/how-to-force-transactional-in-jpa-to-commit-two-repository-action-not-only-just/64399901#64399901 – Ke Vin Oct 19 '20 at 06:01