c12
c12

Reputation: 9827

Spring Data JPARepository and @Transactional For Multiple Operations inside One Method

The saveUser method doesn't save the user object name change when I have multiple operations inside one method. If I use @Transactional(propagation = Propagation.REQUIRED) on top of the saveUser service method, it works fine. When another class creates a new User object and sets all its values and calls the createUser method, it works fine. Why do I need @Transactional for the saveUser method? In what cases do I need to include @Transactional? I'm using Spring Data and JPA (Hibernate impl). Any ideas?

JPA Entity:

@Entity
public class User{
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String name;

//getters/setters..etc

}

Spring Service:

@Service
public class UserServiceImpl{
  @Autowired
  UserRepository userRepository;

  public void saveUser(Long id){
      User user = userRepository.findById(id);
      user.setName("newname");
      userRepository.save(user);
  }

  public void createUser(User user){
      userRepository.save(user);
  }
}

Spring Data JPA/Hibernate Impl Repository:

public interface UserRepository extends JpaRepository<User, Long> {
}

Upvotes: 4

Views: 3521

Answers (2)

TheKojuEffect
TheKojuEffect

Reputation: 21081

The methods in JpaRepository are transactional by default (readonly for retrieving).

Now in your saveUser() method, you need @Transactional because you are retrieving an User by id and updating it and then again persisting to the database. Basically, @Transactional(readOnly=true) is used while reading else @Transactional is used in Spring Data JPA.

 User user = userRepository.findById(id);

returns null to user if no user is found and user.setName("newname"); will give NullPointerException.

Upvotes: 5

Sergi Almar
Sergi Almar

Reputation: 8404

You need transactions if you update the database state (insert/update/delete) otherwise you'll end up having this behaviour.

Even if you do read-only operations in your methods, you should annotate them with @Transactional(readOnly=true) so Spring can optimize the transactional resource.

Upvotes: 0

Related Questions