Средство проверки гибернации, вызывающее многие ко многим отношениям, чтобы не сохранять - PullRequest
1 голос
/ 07 марта 2019

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

В @PostConstruct я сохраняю начальные роли (ADMIN, USER) в базе данных, используя стандартный JpaRepository из spring-data-jpa.Затем я создаю первоначального пользователя с помощью роли администратора.

Если у меня нет своей пользовательской проверки, связь сохраняется правильно, и я вижу запись в user_role таблице присоединения.Если у меня есть проверка, пользователь вставляется в пользовательскую таблицу , но без записи в таблицу user_role. Возвращенный объект имеет роль в наборе ролей, но не сохраняется в БД,Код обобщен ниже.Я не могу понять, как использование RoleRepo для получения всех ролей может каким-либо образом нарушить сохранение, но это так.

class User {
  @Id
  String username;

  @ValidOption
  @ManyToMany(cascade = {CascadeType.ALL //for example}, fetch=FetchType.EAGER)
  Set<Role> roles;
}

class Role {
  @Id
  String name;
}

class CustomValidator implements ConstraintValidator<ValidOption, Object> {
  RoleRepository roleRepo; //injected by spring... have spring factory

  @Override
  public boolean isValid(Object value, ConstraintValidatorContext context){
    roleRepo.findAll() //<-------------- THIS CALL BREAKS THE SAVE
    return true;
  }
}

@Component
class UserCreator {
  RoleRepository roleRepo;
  UserRepo userRepo;

  @PostConstruct
  void setup(){
    Role admin = roleRepo.saveAndFlush(new Role('ADMIN'));
    roleRepo.saveAndFlush(new Role('USER'));

    User user = new User('admin', Collections.singleton(admin));
    userRepo.save(user); //<------ DOES NOT INSERT ADMIN INTO USER_ROLE JOIN TABLE
  }
}

Это работает на 100% точно так, как я ожидал, если бы я удалил пользовательский валидатор,Это также может работать, если я не запустил это в PostConstruct и не запланировал его в другом потоке, мне нужно проверить это.

Проект с воспроизводимым неудачным тестовым примером: https://github.com/tjhelmuth/SPR-22533/blob/master/src/test/java/spr22533/bug/BugExample.java

1 Ответ

2 голосов
/ 07 марта 2019

Доступ к EntityManager во время проверки не гарантируется во время проверки.

Проверка происходит в «методах обратного вызова жизненного цикла». Для них применяется следующее ограничение (Спецификация Java Persistence 2.2; Раздел 3.5.2 Методы обратного вызова жизненного цикла):

В общем случае метод жизненного цикла переносимого приложения не должен вызывать EntityManager или операции запроса, обращаться к другим экземплярам сущности или изменять отношения в том же контексте постоянства. Метод обратного вызова жизненного цикла может изменить состояние отсутствия отношения к объекту, для которого он вызывается.

Чтобы заставить его работать, используйте отдельный EntityManager, который, конечно, может пострадать, увидев другой набор изменений, так как он выполняет другую транзакцию.

См. Также: Правильный способ выполнения запроса EntityManager во время проверки гибернации

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