2016-02-27 2 views
1

Я вызываю метод SLSB, транзакция которого контролируется контейнером. В методе я пытаюсь удалить объект и создать новыйEJB Непонимание сделок

List<FactPlan> factPlans = factPlanFacadeLocal.findAll(); 

for (FactPlan factPlan : factPlans) { 
    factPlanFacadeLocal.remove(factPlan); 
} 

FactPlan factPlan = new FactPlan(12264L, 12088L); 
factPlanFacadeLocal.create(factPlan); 

И я следующее исключение

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "pkfact_plan" 
Detail: Key (fact_id, plan_id)=(12264, 12088) already exists. 

Что я делаю неправильно?

UPD: реализация JPA является EclipseLink

+1

Ну, ошибка говорит все, в таблице 'fact_plan' уже существует запись с идентификатором, которую вы вручную назначает новый объект. Если этот идентификатор принадлежит одному из сущностей, которые вы удалили, попробуйте сделать flush в диспетчере сущностей в методе 'remove' класса' FactPlanFacade' ('em.flush()'). – Geinmachi

+0

@Geinmachi, Да, я понимаю, что говорит ошибка. Я удаляю все записи в таблице fact_table перед вставкой, я показал это в своем коде. Я назначил эти идентификаторы вручную, просто для иллюстрации проблемы с этим выходом. Вопрос в том, что, несмотря на транзакции методов, контролируемые контейнером, я должен делать commit/flushes вручную? – Bagdat

ответ

2

Edit: Я был неправ, говоря, что вам нужно совершить, флеш достаточно после ваших операций вынимаются для обеспечения ограничения БД не нарушаются.

Что происходит (это точно так же для EclipseLink а):

Hibernate только видеть то, что происходит в памяти внутри Persistence контексте транзакции, без промывки он не в состоянии проверить БД ограничений превентивно (первичный ключ в этом случае). В то время как Hibernate прекрасно понимает, что вы уже удаляете элемент с тем же идентификатором (поскольку все это происходило в одном и том же контексте сохранения), БД не видит никаких изменений до сброса.

Теперь вы можете подумать, почему не достаточно, чтобы флеш произошел автоматически, когда транзакция закончилась, до совершения? Разумеется, порядок операций БД будет соответствовать операциям JPA, и БД увидит удаление строки перед вставкой. Ну, это не так, Hibernate меняет порядок ваших операций и помещает все вставки перед удалением, нарушая ограничение DB: http://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/event/def/AbstractFlushingEventListener.html#performExecutions%28org.hibernate.event.EventSource%29