Пакетное обновление режима гибернации

Я пытаюсь обновить коллекцию объекта Java, но порядок, в котором Hibernate выполняет пакетное обновление, приводит к исключению нарушения ограничений. Я буду использовать следующий пример, чтобы объяснить ситуацию.

Entity Student Int id String Name String deskID

Правило: 2 ученика не могут сидеть за одной партой.

1-я транзакция: вставьте 2 учащихся следующим образом Идентификатор учащегося 1: 1 Имя: ABC DeskId: D1

Идентификатор студента 2: 2 Имя: DEF DeskId: D2

Теперь, после этого, я решил обновить обе студенческие сущности, чтобы поменять местами их столы, и я отправляю коллекцию обновленных студенческих сущностей в режим гибернации. Обновление Student 1 Id: 1 Name: ABC DeskId: D2

Идентификатор студента 2: 2 Имя: DEF DeskId: D1

Но это приводит к исключению нарушения ограничений, потому что я думаю, что обновление происходит по одной записи за раз.

Я использую менеджеры сущностей JTA для управления транзакциями. Мой код для обновления выглядит примерно так

updateMultiple(Collection<Student> updatedStudents)
        for (final Student student: updatedStudents)
        {
            final Student st= this.entityManager.getReference(Student.class, Student.getId());
            student.merge(st);
        }
        this.entityManager.flush();
        return breakClauseDtos;

person Prim    schedule 02.10.2012    source источник


Ответы (1)


Источник вашей проблемы ясен: база данных проверяет ограничения при выполнении инструкции SQL, а не во время фиксации. При выполнении первого оператора SQL ограничение нарушается.

Вы можете обойти проблему, если сначала удалите стол у ученика 1, затем назначите его ученику 2, а затем отдайте ученику 1 его описание. Это означает три оператора SQL (на один больше, чем необходимо), а затем, возможно, вам придется сбрасывать сеанс после каждого обновления (Hibernate переупорядочивает операторы SQL, что может помешать вашему ручному порядку).

Но лучшим решением является исправление проблемы в вашей модели данных.

Если каждой партой может владеть только один ученик, то существует отношение n:1 между партой и учеником. Рабочему столу нужен идентификатор студента в качестве внешнего ключа. Никаких дополнительных ограничений не требуется. Теперь изменение парты означает изменение идентификатора студента в записи парты. Это можно сделать только с двумя операторами обновления.

person Johanna    schedule 02.10.2012
comment
спасибо за ваш ответ, на самом деле моя модель данных сложнее, чем эта. Хорошим примером для представления моей проблемы может быть то, что у студента есть 2 свойства Дата начала и Дата окончания, и у меня есть ограничение на БД, говорящее, что никакие 2 студента не должны иметь перекрывающиеся даты начала и окончания... Это означает, что мы не можем иметь учащийся с датой начала: 1 и датой окончания: 4 и другой учащийся с датой начала: 2 и датой окончания: 6 - person Prim; 02.10.2012