Transactionality
By default, CRUD methods on repository instances are transactional. For read operations, the transaction configuration readOnly
flag is set to true
. All others are configured with a plain @Transactional
so that default transaction configuration applies. For details, see JavaDoc of SimpleJpaRepository
. If you need to tweak transaction configuration for one of the methods declared in a repository, redeclare the method in your repository interface, as follows:
public interface UserRepository extends CrudRepository<User, Long> {
@Override
@Transactional(timeout = 10)
public List<User> findAll();
// Further query method declarations
}
Doing so causes the findAll()
method to run with a timeout of 10 seconds and without the readOnly
flag.
Another way to alter transactional behaviour is to use a facade or service implementation that (typically) covers more than one repository. Its purpose is to define transactional boundaries for non-CRUD operations. The following example shows how to use such a facade for more than one repository:
@Service
class UserManagementImpl implements UserManagement {
private final UserRepository userRepository;
private final RoleRepository roleRepository;
@Autowired
public UserManagementImpl(UserRepository userRepository,
RoleRepository roleRepository) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
}
@Transactional
public void addRoleToAllUsers(String roleName) {
Role role = roleRepository.findByName(roleName);
for (User user : userRepository.findAll()) {
user.addRole(role);
userRepository.save(user);
}
}
This example causes call to addRoleToAllUsers(…)
to run inside a transaction (participating in an existing one or creating a new one if none are already running). The transaction configuration at the repositories is then neglected, as the outer transaction configuration determines the actual one used. Note that you must activate <tx:annotation-driven />
or use @EnableTransactionManagement
explicitly to get annotation-based configuration of facades to work. This example assumes you use component scanning.
Transactional query methods
To let your query methods be transactional, use @Transactional
at the repository interface you define, as shown in the following example:
@Transactional(readOnly = true)
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastname(String lastname);
@Modifying
@Transactional
@Query("delete from User u where u.active = false")
void deleteInactiveUsers();
}
Typically, you want the readOnly
flag to be set to true
, as most of the query methods only read data. In contrast to that, deleteInactiveUsers()
makes use of the @Modifying
annotation and overrides the transaction configuration. Thus, the method runs with the readOnly
flag set to false
.
You can use transactions for read-only queries and mark them as such by setting the |