#java #hibernate #spring #orm #persistence
#java #спящий режим #весна #orm #сохранение
Вопрос:
У меня есть объект гибернации, который имеет одно или несколько <many-to-one
сопоставлений, например
<hibernate-mapping>
<class name="MyClass" table="my_table">
<cache usage="nonstrict-read-write"/>
<composite-id>
<key-property name="id" length="30"/>
<key-property name="someRef" length="30" column="foreign_key_to_something"/>
</composite-id>
<many-to-one name="mappedProperty" column="foreign_key_to_something" insert="false" update="false"/>
<property name="foo" column="foo"/>
...
</class>
</hibernate-mapping>
Мне нужно создать такую сущность и получить немедленный доступ к mappedProperty
ней после создания. Я вижу здесь два подхода:
1) Создайте объект и установите все связанные <many-to-one
сопоставления вручную. Очевидным недостатком этого подхода является требуемая работа, особенно если количество отображаемых <many-to-one
объектов велико. Зачем делать что-то вручную, если фреймворк может сделать это за вас?
2) Создайте объект, только инициализировав необходимые параметры (например, первичные ключи id
и someRef
в приведенном выше случае), затем сохраните и повторно загрузите его немедленно. Загрузка должна инициализироваться mappedProperty
автоматически или обеспечивать отложенную инициализацию по требованию.
Я предпочитаю вариант 2), однако я заметил, что в некоторых случаях mappedProperty
свойство не задано. load()
возвращает тот же объект, который я передал create()
, только с инициализированными первичными ключами. Я все еще не уверен, почему это происходит, но чтобы бороться с этим, мне пришлось бы отсоединить объект от сеанса гибернации, чтобы load()
он был вынужден перейти к базе данных и получить заново. Опять же, звучит довольно сложно, не так ли?
Я что-то здесь упускаю? Существуют ли какие-либо другие способы решения этой проблемы?
Ответ №1:
Когда вам нужно обновить состояние объекта из базы данных, используйте refresh()
.
Комментарии:
1. Примечание: если кто-то еще будет использовать этот подход, не забудьте сделать
session.flush()
это раньшеrefresh()
. Для получения более подробной информации см.: forum.hibernate.org /…
Ответ №2:
load
и get
верните объект из сеанса, если он уже есть. Таким образом, ваш второй вариант потребует, чтобы вы очистили, затем удалили объект из сеанса, а затем перезагрузили его (выполнив запрос select для известных вам данных). Вызов обновления сделал бы то же самое, проще, но все равно выдал бы дополнительный запрос select ни для чего.
Я действительно предпочитаю первый вариант: просто убедитесь, что каждый раз, когда устанавливается ассоциация, также отображается соответствующее сопоставленное свойство. Вы несете ответственность за согласованность и инварианты объектов (как и в случае двунаправленных ассоциаций, где должны поддерживаться обе стороны).
Третьим вариантом было бы полностью удалить сопоставленное свойство и просто вызвать entity.getKey().getSomeRef().getId() .
Комментарии:
1. Спасибо, но, как я уже сказал, с первым вариантом действительно неудобно работать, если ваша сущность имеет несколько сопоставлений. Некоторые из моих объектов имеют около 10 зависимых объектов, и установка их всех была бы кошмаром: (