У меня есть таблица БД (Postgres) с уникальным ограничением для одного столбца. У меня есть тест, отмеченный аннотацией @Transactional, который обновляет это уникальное значение столбца до неуникального значения. Я ожидаю, что операция обновления завершится ошибкой, но она выполняется успешно. Более того, когда я получаю обновленный объект из базы данных (внутри той же транзакции), значение столбца там обновляется.
Упрощенная версия сущности JPA:
@Entity
@Table(name = "entities")
public class Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// The unique column
@Column(name = "name", unique = true)
@NotNull
private String name;
...
}
Упрощенная версия для теста:
@Test
@Transactional
public void test() {
Entity firstEntity = new Entity();
firstEntity.setName("First Entity Name");
// This just calls corresponding JPA repository .save method
entityService.create(firstEntity);
Entity secondEntity = new Entity();
secondEntity.setName("Second Entity Name");
entityService.create(secondEntity);
// Update name to a not unique value
secondEntity.setName(firstEntity.getName);
// This calls corresponding JPA repository .save method.
// It also catches DataIntegrityViolationException and throws
// a more user friendly exception instead
entityService.update(secondEntity);
}
Этот код работает так, как я ожидаю, если аннотация @Transactional удалена или транзакция зафиксирована. Я также пытался вызвать EntityManager.flush(), как указано здесь, но этот код выдает ConstraintViolationException после сброса результирующих данных, поэтому я не могу проверить, что мой метод entityService.update работает правильно и выдает правильное исключение.
Также обратите внимание, что если я попытаюсь создать новую запись с неуникальными данными в транзакционном тесте (не с обновлением), тогда тест будет работать так, как ожидалось — DataIntegrityViolationException генерируется, когда создается неуникальный объект.
Может ли кто-нибудь пояснить, можно ли заставить сценарий обновления работать должным образом, сохраняя транзакцию теста, чтобы мне не нужно было заботиться об очистке данных?
@Transactional
, что означает, что исключение возникнет только ПОСЛЕ завершения выполнения метода службы. Если вам действительно нужно то, что у вас есть, позвонитеsaveAndFlush
(но я бы посчитал это антипаттерном). - person M. Deinum   schedule 19.04.2017create
, поскольку без этого еще ничего не сохраняется). Из-за большей границы tx ваш тест не пройден. - person M. Deinum   schedule 20.04.2017create
? т.е. создать объект 1, а затем создать объект 2 с тем же именем в тех же транзакциях. Это работает так, как я ожидаю, т.е. создание entity2 не удается. Не могли бы вы уточнить это, если можно? - person knesterovich   schedule 20.04.2017