Начиная с Java 8, есть еще одна возможность, которую я предпочитаю по причинам, указанным ниже:
@Service
public class UserService {
@Autowired
private TransactionHandler transactionHandler;
public boolean addUsers(List<User> users) {
for (User user : users) {
transactionHandler.runInTransaction(() -> addUser(user.getUsername, user.getPassword));
}
}
private boolean addUser(String username, String password) {
// TODO
}
}
@Service
public class TransactionHandler {
@Transactional(propagation = Propagation.REQUIRED)
public <T> T runInTransaction(Supplier<T> supplier) {
return supplier.get();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public <T> T runInNewTransaction(Supplier<T> supplier) {
return supplier.get();
}
}
Этот подход имеет следующие преимущества:
1) Может применяться к частных методов.Таким образом, вам не нужно нарушать инкапсуляцию, делая метод общедоступным только для удовлетворения ограничений Spring.
2) Один и тот же метод может быть вызван при различном распространении транзакции, и это зависит от вызывающей стороны выбрать подходящий.Сравните эти 2 строки:
transactionHandler.runInTransaction(() -> userService.addUser(user.getUserName, user.getPassword));
transactionHandler.runInNewTransaction(() -> userService.addUser(user.getUserName, user.getPassword));
3) Это явно, поэтому более читабельно.