У меня длинный вопрос, так как вначале я написал полный список того, что я тестировал, поэтому, пожалуйста, либо закончите чтение, либо перейдите к самому вопросу.
Я создаю таблицу в базе данных PostgreSQL:
create table if not exists users
(
id bigserial not null
constraint users_pkey
primary key,
name varchar(50),
is_active boolean not null,
old_user bigint
constraint users_users_id_fk
references users
);
alter table users owner to postgres;
create unique index if not exists users_id_uindex on users (id);
create unique index if not exists users_is_active_idx
on users (is_active) where (is_active = true);
Может быть только один активный пользователь.
Я создаю приложение для загрузки Spring. Ниже описание конструкции (очень простое) и под ним сам вопрос.
1) Сущность:
@Data
@NoArgsConstructor
@Entity
@Table(name = "users")
public class User {
public User(String name, Boolean isActive, User oldUser) {
this.name = name;
this.isActive = isActive;
this.oldUser = oldUser;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "is_active")
private Boolean isActive;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "old_user")
private User oldUser;
}
2) Репозиторий:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
3) Сервис:
@Service
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public User getOne(Long id) {
return userRepository.getOne(id);
}
@Override
public User save(User user) {
return userRepository.save(user);
}
@Override
public User saveAndFlush(User user) {
return userRepository.saveAndFlush(user);
}
}
Вставляю одного активного пользователя: INSERT INTO "public"."users" ("id", "name", "is_active", "old_user") VALUES (DEFAULT, 'FirstUser', true, NULL)
И теперь я хочу вставить второго пользователя (активного), но из приложения:
@Slf4j
@Component
public class TestBean implements CommandLineRunner {
private final UserService userService;
public TestBean(UserService userService) {
this.userService = userService;
}
@Override
@Transactional
public void run(String... args) throws Exception {
log.info("Start...");
User first = userService.getOne(1L);
User secondUser = new User("SecondUser", true, first);
userService.saveAndFlush(secondUser);
}
}
Если я запускаю сервер, я получаю исключение: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "users_is_active_idx"
Чтобы исправить это, я должен сначала деактивировать старого пользователя, а затем активировать нового. Но это просто не сработает, поэтому, прежде чем я активирую нового пользователя, я должен сбросить его в контекст:
User first = userService.getOne(1L);
first.setIsActive(false);
userService.saveAndFlush(first);
User secondUser = new User("SecondUser", true, first);
userService.saveAndFlush(secondUser);
И это решение отлично работает. Но теперь я добавляю в сервис новый метод:
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public User saveInRequiredNew(User user) {
return userRepository.saveAndFlush(user);
}
И попробуйте спасти пользователя этим методом:
User first = userService.getOne(1L);
first.setIsActive(false);
userService.saveAndFlush(first);
User secondUser = new User("SecondUser", true, first);
User user = userService.saveInRequiredNew(secondUser);
log.info(String.valueOf(user.getId()));
В этом случае, когда я вызываю метод saveInRequiredNew, мое приложение не генерирует исключения и не дает результата. он просто перестает работать. В реальном приложении моя логика построена так, что я должен сохранить объект в транзакции с помощью Propagation.REQUIRES_NEW.
Мой вопрос - почему это происходит и какое будет решение? Можно обновить обе сущности (старых и новых пользователей за одну транзакцию (Propagation.REQUIRES_NEW). Я не знаю, правильно ли это)
@Simon Martinelli просто перестает принимать запросы, не отображает ошибок, не отображает ответы, не выходит из debbag. как будто в рабочем состоянии но ни на что не реагирует
И вы уверены, что у вас нет активной точки останова? Что, если запустить без отладки?
да, если я нажму F9 и у меня будет точка останова на следующей строке, я не войду в эту строку
а поток все еще работает?
похоже, что основной поток работает





Что вы имеете в виду под словом «перестает работать»?