В этой статье разберем проблемы, которые приводят к тому, что Hibernate не сохраняет объект в базу с ошибкой could not execute statement; SQL [n/a]; constraint [“id" of relation "ProblemClass”];: частые проблемы и пути их решения.
Другими словами: “У меня не сохраняется объект в базу. Как мне это исправить?”
Эта ошибка сигнализирует о нарушении ограничения (constraint violation) при попытке сохранить объект в базу данных, а именно проблемы с генерацией id.
Вариант 1. Проверьте настройку генерации
В сущностях Hibernate используется аннотация @GeneratedValue для генерации идентификатора записи в таблице, а в самой таблице поле id должно быть автоинкрементируемое.
Возможное решение:
1. Для того, чтобы узнать, явзяется ли поле автоинкрементируемым можно воспользоваться следующей командой:
SELECT column_name, column_default FROM information_schema.columns WHERE table_name = 'target_date' AND column_name = 'id';
1.1 В PostgreSQL, например, автоинкрементное поле можно создать при помощи использования типа данных bigserial
create table problem_class (
id bigserial primary key,
...
);
1.2. Если таблица уже существует, можно добавить автоинкремент с помощью команды:
alter table problem_class alter column id set default nextval('problem_class_id_seq');
2. Добавьте аннотацию @GeneratedValue для поля id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
open var id: Long? = null
Вариант 2. Проверьте, что значения id не выставляются вручную
Ошибка также может возникнуть, если вы случайно задаёте значение id вручную перед сохранением объекта, что приводит к конфликту с автоинкрементным значением.
Возможное решение:
При создании нового объекта убедитесь, что значение id остаётся null. В таком случае значение id будет сгенерировано автоматически при сохранении записи.
Вариант 3. Проверьте, что у связных объектов присутствует двусторонняя связь и каскадирование
Когда вы сохраняете объект ParentClass, связанные с ним объекты ProblemClass не сохраняются автоматически, если не включено каскадирование операций. Вам нужно явно указать, что при сохранении ParentClass должны сохраняться и связанные объекты ProblemClass. И убедитесь в существовании связи с обратной стороны
Возможное решение:
Чтобы это сделать, добавьте свойство cascade = [CascadeType.ALL] в аннотацию @OneToMany для поля problemClass в объекте ParentClass
@OneToMany(fetch = FetchType.EAGER, mappedBy = "parentClass", cascade = [CascadeType.ALL])
open var problemClass: MutableSet<ProblemClass> = mutableSetOf()
С обратной стороны эта связь должна выглядеть следующим образом:
@ManyToOne @JoinColumn(name = "parent_class_id")
open var parentClass: ParentClass