2015-09-03 4 views
0

Я пишу мастера для установки довольно сложной объектной модели. Желаемое поведение - загрузить значения в мастер из базы данных с помощью JPA, отредактировать их через различные текстовые поля и поля со списком и записать только , если пользователь нажимает кнопку «Готово» в конце. Если пользователь нажимает «Отмена», я хочу, чтобы содержимое базы данных оставалось таким, каким оно было.Редактор сущности JPA, сохраняется только на OK

Подход, который я имею в виду:

EntityManager em1; // From the Factory 
EntityTransaction tx1 = em1.getTransaction(); 
tx1.begin(); 
List<?> docs = em1.createQuery("select d from DocumentRoot d").getResultList(); 
DocumentRoot doc = (DocumentRoot)docs.get(0); 
tx1.commit(); 
em1.close(); // Now DocumentRoot and all associated objects are detached 

if (DocumentEditor.showEditDialog(doc) == APPROVE) { // Mutates doc up the wazoo 
    EntityManager em2; // From the Factory 
    EntityTransaction tx2 = em2.getTransaction(); 
    tx2.begin(); 
    em2.merge(doc); 
    tx2.commit(); 
    em2.close(); 
} 

Существует, вероятно, какой-то баланс аннотаций, которые делают эту работу, но я не наткнулся на него. Я добавил cascade = CascadeType.ALL на все мои один-ко-многим и т.д. ассоциации, которые укрепляли «object references an unsaved transient instance» ошибку, но теперь у меня есть «Multiple representations of the same entity [...] are being merged.»

У меня есть подозрение, что рассматриваемый объект многократно представлен, потому что есть многие-ко-многим. Там есть another thread, предлагая удалить CascadeType.MERGE из ссылок на этот объект, но это похоже на опасно протекающую бандаду. Неудивительно, что удаление этого CascadeType.MERGE означает, что новые объекты типа не сохранялись при слиянии.

Кажется, что весь этот подход - отсоединить, отредактировать, слить, если он принят, делает JPA очень несчастным. Есть ли другой подход, который считается более идиоматичным для случаев, когда вы хотите редактировать то, что является фактически локальной копией, не сохраняясь и сохраняться только тогда, когда пользователь нажимает «ОК?».

+0

Отменить откат(), а не commit()? – Gimby

ответ

0

Вы правы, я также испытал, что редактирование объектов JPA является громоздким при использовании режима detach -> edit -> merge.

Если вы используете Java EE, лучшим подходом является использование entityManager в расширенном режиме, как Adam Bien explains in his blog. Он описывает, как создавать шлюзы вместо фасадов/DAO, но то, что вам нужно, - это stateful EJB, в котором хранится сущностьManager с расширенным контекстом (@PersistenceContext(type=PersistenceContextType.EXTENDED)). EJB должен храниться в компоненте, зависящем от сеанса (любая другая область, которая содержит как извлечение данных, так и сохранение в порядке)).

Подробнее о расширенном EM here.

Если вы не используете Java EE, позаботьтесь о местах, где вы копируете объекты, которые вы не копируете по ссылке, но всегда создавайте новый объект, если они действительно представляют собой другой экземпляр (дополнительная информация о проблема: https://hibernate.atlassian.net/browse/HHH-9106).

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

Смежные вопросы