Каскад гибернации + проблема составного идентификатора

В настоящее время я изучаю Hibernate и столкнулся с этой проблемой: я определил 3 объекта: пользователь, модуль, разрешение. И пользователь, и модуль имеют отношение «один ко многим» с разрешением, поэтому составной идентификатор разрешения состоит из idUser и idModule. Класс пользователя имеет свойство, представляющее собой набор разрешений, и оно соответствующим образом аннотировано с помощью @OneToMany, cascade=CascadeType.ALL и т. д.

Теперь я создал классы с функцией обратного проектирования MyEclipse. Идентификатор разрешения был создан как отдельный класс, который имеет свойство idUser и idModule. Я думал, что могу создать пользователя, добавить ему какие-то новые разрешения, и, таким образом, сохранение пользователя приведет к каскадной операции, и разрешения будут сохранены автоматически. Это верно, за исключением того, что операция вызывает исключение. Я запускаю следующий код:

Permission p = new Permission();
p.setId(new PermissionId(null, module.getId());
user.getPermissions().add(p);
session.save(user);

У меня проблема в том, что, хотя SQL генерируется правильно (сначала сохраняет пользователя, затем разрешение), я получаю сообщение об ошибке от драйвера базы данных (Firebird), в котором говорится, что он не может вставить нулевое значение для idUser, что верно, но разве спящий режим не должен передавать вновь созданный идентификатор пользователя второму запросу?

Этот конкретный сценарий кажется мне очень нелогичным, поскольку я склонен передавать нулевой идентификатор объекту Permission, поскольку он новый, и я хочу, чтобы он был создан, но, с другой стороны, я должен установить свойство idModule, поскольку модуль уже существует, поэтому я не совсем понимаю, как должна работать такая операция.

Кто-нибудь знает, что я делаю неправильно? Спасибо


person JayPea    schedule 18.10.2011    source источник


Ответы (1)


Вам необходимо указать каскадное действие для выполнения Hibernate при сохранении User с прикрепленным переходным процессом (то есть еще не сохраненным) Permission.

Кстати, вы можете рассмотреть возможность использования другой стратегии ID для объекта Permission, например сгенерированного значения ID — как может первичный ключ строки permission в базе данных содержать нулевое значение?

person matt b    schedule 18.10.2011
comment
Спасибо. Но разве Cascade.ALL не работает для всех действий? Объект Permission не может иметь нулевое значение. Проблема в том, что я должен установить для свойства idUser значение null, так как пользователь еще не создан. Я думал, что каскадная операция передаст это значение объекту Permission после сохранения объекта пользователя. Как я уже сказал, операция генерирует оба запроса (вставить пользователя, вставить разрешение), просто часть, которая вставляет разрешение, не имеет доступа к вновь созданному идентификатору пользователя. - person JayPea; 18.10.2011
comment
Если вы намерены сгенерировать идентификатор разрешения, вам не следует устанавливать для него ненулевое значение. Hibernate необходимо знать, должен ли он генерировать идентификатор для объекта или нет, и по умолчанию это делается с использованием несохраненного значения null для идентификаторов — см. эту часть руководство. Однако обратите внимание, что это относится к трудностям, связанным с составными идентификаторами. Наконец, мое предложение об использовании сгенерированного значения (например, автоинкремента) относилось к идентификатору разрешения, а не к разрешению. - person matt b; 18.10.2011
comment
Проблема в том, что в этом случае, поскольку идентификатор является составным, одна часть идентификатора является новой (идентификатор пользователя), а другая — нет (идентификатор модуля из уже существующего объекта модуля). Поэтому я должен установить хотя бы модульную часть идентификатора вручную, иначе он не будет правильно ссылаться на сущность модуля. Но, если я правильно понимаю, я должен оставить все свойство id равным нулю, иначе оно не будет работать? - person JayPea; 18.10.2011
comment
Спасибо, в этой части руководства не показано, как это можно сделать с составным идентификатором. Я начинаю думать, что это просто не поддерживается в этом сценарии. Я думаю, что вместо этого я собираюсь вставить объекты разрешений вручную. - person JayPea; 18.10.2011