2016-08-15 6 views
1

У меня есть уникальная проблема валидации поля. Это может относиться к любому уникальному полю на любом объекте, но в моем случае прямо сейчас у меня есть пользователь, и я хочу, чтобы имя пользователя было уникальным в базе данных.Пропустить проверку уникального ограничения бина при редактировании существующего объекта

отрывок из моего пользователя:

@Entity 
public class User { 

    @NotNull 
    @Column(unique = true) 
    @UniqueUsername 
    private String username; 
} 

UniqueUsername обычая ограничение аннотация следующим образом:

@Constraint(validatedBy = {UniqueUsernameValidator.class}) 
public @interface UniqueUsername { 

    String message() default "User already exists with this username"; 

    Class<?>[] groups() default {}; 

    Class<? extends Payload>[] payload() default {}; 
} 

Тогда UniqueUsernameValidator обычая ограничения валидатор, который просто проверяет базу данных для существующего пользователя с данное имя пользователя:

@ApplicationScoped 
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> { 

    @Inject 
    private UserRepository userRepo; 

    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
     boolean valid = false; 
     try { 
      userRepo.findByUsername(value); 
     } catch (NoResultException e) { 
      // No result means username not already used 
      valid = false 
     } 
     return valid; 
    } 
} 

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

В идеале мой валидатор, вероятно, будет иметь доступ к/знанию проверяемого объекта пользователя (а не только значения поля), чтобы я мог проверить, был ли дублирующийся объект, который я нашел в базе данных, таким же, как и редактируемый. Но я не могу найти способ сделать это в своем валидаторе.

Кто-нибудь еще сталкивается с этой проблемой и придумывает приемлемое решение?

ответ

0

Как использовать комбинацию имени пользователя и сгенерированного первичного ключа (ID). Использование идентификатора для ссылок будет еще быстрее, и вы получите дополнительную информацию, которая может быть разрешена при обновлении или создании нового объекта.

Ваша проверка должна быть перенесена на уровень сущности, а затем вы можете проверить, имеет ли сущность нулевой идентификатор (создание нового) или имеет некоторый идентификатор (обновление существующего).

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

Как вы писали, эта ситуация касается не только пользователя, но и объектов в целом, и этот подход может решить и ситуацию с несколькими уникальными полями.

-1

Я сталкиваюсь с той же проблемой, я пропустил валидатор для действия обновления таким образом:

@Override 
public boolean isValid(String email, ConstraintValidatorContext constraintValidatorContext) { 

    StackTraceElement[] elements = Thread.currentThread().getStackTrace(); 

    for (int i = 0; i < elements.length; i++) { 
     StackTraceElement element = elements[i]; 
     if(element.getMethodName().equals("preUpdate")){ 
      return true; 
     } 
    }