Пользовательская проверка Grails - Запрос проверки проверки - Что происходит при обновлении? - PullRequest
5 голосов
/ 10 августа 2010

У меня есть собственный валидатор, такой как -

validator: { userEmail, userAccount ->

   if (userAccount.authenticationChannel == "ABC") {
      boolean valid = true;
      UserAccount.withNewSession {
      if (UserAccount.findByEmail(userEmail)){
         valid = false;
      }
      else if (UserAccount.findByName(userEmail)) {
         valid = false;
      }

...

Так что в основном мне нужна некоторая проверка, основанная на каком-то условии, и в моей проверке мне нужно выполнить запрос.

Но теперь, если я это сделаю -

def admin = new UserAccount(firstname:'Admin',email:'admin@example.com')


admin.save(flush:true)


admin.addToAuthorities("ADMIN").save(flush:true)

Сбой.

Grails выполняет проверку, даже при обновлении, и, поскольку электронная почта существует, проверка не выполняется.Чем это отличается, если я делаю

email {unique:true}

Говорит ли Граилс, что я не могу написать собственный валидатор, который проверяет уникальность.

Ответы [ 3 ]

6 голосов
/ 29 января 2013

Не уверен, если это ваша проблема или нет, но когда я попытался создать такую ​​проверку (например, ту, которая выполняет запросы к базе данных), я получил бы StackOverflowError.Причина в том, что при запуске запроса (например, findByEmail) Hibernate попытается сбросить сеанс, что заставит его проверить все временные объекты, что, в свою очередь, снова вызовет ваш пользовательский валидатор, что приведет к бесконечной рекурсии.

Хитрость для предотвращения этого - установить режим сброса сеанса на «ручной» на короткое время при выполнении запросов.Это не позволяет Hibernate пытаться сбросить сессию перед выполнением запросов.Побочным эффектом является то, что ваш запрос не будет возвращать сущности, которые вы создали в текущем сеансе, но еще не были сохранены (сброшены) в базе данных.

UserAccount.withNewSession { session ->
    session.flushMode = FlushMode.MANUAL
    try {
        if (UserAccount.findByEmail(userEmail)){
            valid = false;
        }
        else if (UserAccount.findByName(userEmail)) {
            valid = false;
        }
    }
    finally {
        session.setFlushMode(FlushMode.AUTO);
    }
}

См. UniqueConstraint для примера того, как это делается.

0 голосов
/ 12 августа 2010

Спасибо.Я могу заставить это работать. Admin.save () вызывает проверку как при вставке, так и при обновлении.Я обработал оба случая (вставка и обновление) и смог заставить это работать.

0 голосов
/ 10 августа 2010

Альтернативой может быть проверка в методе сохранения.

def save = {
  ..
  if (some_checks_succeed(userEmail, userAccount)) {
    admin.save(flush: true)
  }
  ..
}

def some_checks_succeed = { String userEmail, String userAccount ->
  boolean valid = true;
  if (userAccount.authenticationChannel == "ABC") {
    UserAccount.withNewSession {
    if (UserAccount.findByEmail(userEmail)) {
     valid = false;
    } else if (UserAccount.findByName(userEmail)) {
     valid = false;
    }

    ..
  }

  return valid
}

Некоторые модификации могут потребоваться, но приведенный выше код дает вам пример

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...