Проверка существования транзакции в режиме гибернации

#hibernate #spring #transactions #hibernate-annotations

#спящий режим #весна #транзакции #режим гибернации-аннотации

Вопрос:

У меня возникла аналогичная проблема с человеком, который опубликовал это сообщение на форумах Spring:http://forum.springsource.org/archive/index.php/t-20943.html

По сути, я пишу функцию автоматической регистрации для веб-сайта, над которым я работаю. Если пользователь существует в сторонней базе данных, из которой мы переносим пользователей, а не в нашей БД, то процесс входа в систему автоматически создаст пользователя в нашей БД.

Для этого я должен сначала попытаться аутентифицировать пользователя при входе в систему с помощью электронной почты и пароля. Если это не удается, я проверяю стороннюю базу данных и пытаюсь создать пользователя, используя эту информацию. Как и в приведенной выше ссылке, похоже, что эта проверка существования, за которой следует вставка, приводит к тому, что метод помечается Hibernate только как откат.

Я попытался использовать транзакционные требования для проверки существования, чтобы принудительно включить их в новую транзакцию, я надеялся, что эта транзакция будет помечена как откат только вместо родительской транзакции, но это не сработало.

Кто-нибудь может посоветовать, как это сделать? Приведенная выше ссылка предлагает вставить и использовать ошибку дубликата ключа в качестве проверки того, что пользователь уже существует, но это кажется беспорядочным и потребует значительного изменения дизайна.

кстати, мы используем Hibernate, Spring и аннотации для обработки транзакций.

Ответ №1:

Предполагая, что метод login выдает исключение, вы можете исправить это, добавив параметр noRollbackFor к вашему атрибуту @Transactional в методе проверки существования.

 @Transactional(noRollbackFor=SecuirtyExcepion.class)
public boolean authenticate(String email,String password) throws SecurityException {

}

@Transactional
public void someMethod() {
  try {
   // without noRollbackFor this would result in transaction being marked as 
   // rollback only 
    authenticate(email,password); 

  } catch(SecurityException e) {
    // create user

  }
}
  

Комментарии:

1. Извините, но проблема не в этом. Проблема в том, что у Hibernate, похоже, есть особенность: если вы проверяете наличие чего-либо, а затем создаете этот объект, это приведет к откату.

Ответ №2:

Решение, которое я нашел, заключается в разделении соответствующих разделов на отдельные транзакции. В моем случае я проверяю, существует ли пользователь, тогда, если это не так, но это происходит в моей сторонней базе данных, создающей его. Это означает, что в случае сбоя аутентификации создание нового пользователя не будет отменено, но если это требуется, его можно разделить по-другому, чтобы методы create и authenticate находились в одном и том же транзакционном методе.

 public void login(String username, String password)
{
   User user = null;
   try {
      user = userHelper.findUserByUsername(username);
   } catch (UserNotFoundException e) {
      log.warn(e);
      if (integrationLayer.checkUserExists(username))
      {
         user = userHelper.createUser(username, password);
      }
      else
      {
         return false;
      }
   }

   return userHelper.authenticate(user, password);
}

@Transactional
public User userHelper.findUserByUsername(String Username)
{
   ... find and return user ...
   ... throw user not found exception if not found ...
}

@Transactional
public User userHelper.createUser(String Username, String Password)
{
   ... create and return the new user ...
}


@Transactional
public Boolean userHelper.authenticate(String Username, String Password)
{
   ... authenticate the user ...
}

@Transactional
public Boolean integrationLayer.checkUserExists(String username)
{
   ... if the user exists in the third party DB return true ...
}