У меня есть EJB, целью которого является копирование пользователей из другой системы в мою, путем создания пользователя в случае его отсутствия или обновления существующего пользователя с тем же идентификатором. Используются три метода:
@Schedule(second = "0", minute = "0", hour = "0", persistent = false)
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public void timer(){
updateUserDB();
// Some other stuff
}
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public void updateUserDB(boolean delta) {
// Find users in external system
for(every user in the external system) {
createUser(externalUser);
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private void createUser(User externalUser) {
try{
em.persist(user);
em.flush();
return;
}catch(Exception e){} // Logs
em.clear(); // Make sure the user is removed from the persistence context (or it will try to add it again if an error occured at the next flush
context.setRollbackOnly(); // Rollback if error occured
Сценарий, который я ищу, состоит в том, чтобы сохранить всех пользователей, если произошла ошибка, я хочу зарегистрировать это и откатить это единственное сохранение, а затем продолжить с остальными пользователями. Так что REQUIRES_NEW
на createUser()
имеет смысл. Другими словами, в общей сложности должно быть х количество транзакций, где х - количество пользователей.
Проблема
Документация по EJB охватывает только то, должен ли вызываемый метод начинать транзакцию или нет, но как я должен аннотировать вызывающие ("клиентские") методы; timer()
и updateUserDB
правильно? NOT_SUPPORTS и SUPPORTS заставляют ejb выдавать TransactionRequiredException
при достижении em.persist(user)
внутри createUser()
, что, я думаю, не имеет смысла, поскольку createUser()
должно быть разрешено начинать новую транзакцию при вызове из метода SUPPORTS. Если я аннотирую вызывающие методы с помощью REQUIRED, пользователи вообще не сохраняются, похоже, что откат влияет на большую транзакцию, а не на маленькую (на пользователя) транзакцию.
Как аннотировать эти три метода, чтобы получить желаемый эффект?
Редактировать
Если для обоих методов вызова установлено значение Required, JTA не выдает исключение, но транзакция по какой-то причине откатывается каждый раз, даже если я удаляю context.setRollbackOnly()
.