Reputation: 9827
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
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
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