JPA с JTA: сохранить сущность и объединить каскадные дочерние сущности

У меня двунаправленное отношение «один ко многим» со следующими классами сущностей:

0 or 1 client <-> 0 or more product orders

При сохранении объекта клиента я хочу, чтобы связанные объекты заказа продукта также сохранялись (так как их внешний ключ к «родительскому» клиенту мог быть обновлен).

Конечно, все необходимые параметры CASCADE устанавливаются на стороне клиента. Ноit does not work if a newly created client is persisted for the first time while referencing an existing product order как в этом сценарии:

product order '1' is created and persisted. Works fine. client '2' is created and product order '1' is added to its product orders list. Then it is persisted. Does not work.

Я перепробовал несколько аппроксимаций, но ни один из них не показал ожидаемого результата. Смотрите эти результаты ниже. Я прочитал все связанные вопросы здесь, но они не помогли мне. Я использую EclipseLink 2.3.0, чистые аннотации JPA 2.0 и JTA в качестве типа транзакции в оперативной БД Apache Derby (JavaDB) на GlassFish 3.1.2. Отношения сущностей управляются графическим интерфейсом JSF. Управление отношениями на уровне объектов работает (не говоря уже о сохранении), я тестировал его с помощью тестов JUnit.

Approach 1) "Default" (based on NetBeans class templates)

Клиент:

@Entity
public class Client implements Serializable, ParentEntity {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(mappedBy = "client", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},
            fetch= FetchType.LAZY)
    private List<ProductOrder> orders = new ArrayList<>();

    // other fields, getters and setters
}

ProductOrder:

@Entity
public class ProductOrder implements Serializable, ChildEntity {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne // owning side
    private Client client;

    // other fields, getters and setters
}

Общий Фасад Постоянства:

// Called when pressing "save" on the "create new..." JSF page
public void create(T entity) {
    getEntityManager().persist(entity);
}

// Called when pressing "save" on the "edit..." JSF page
public void edit(T entity) {
    getEntityManager().merge(entity);
}

Результат:

create () генерирует это исключение немедленно:

Warning: A system exception occurred during an invocation on EJB ClientFacade method public void javaee6test.beans.AbstractFacade.create(java.lang.Object) javax.ejb.EJBException: Transaction aborted ...

Caused by: javax.transaction.RollbackException: Transaction marked for rollback. ...

Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The state-ment was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL120513133540930' defined on 'PRODUCTORDER'. Error Code: -1 Call: INSERT INTO PRODUCTORDER (ID, CLIENT_ID) VALUES (?, ?) bind => [2 parameters bound] Query: InsertObjectQuery(javaee6test.model.ProductOrder[ id=1 ]) ...

Caused by: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL120513133540930' defined on 'PRO-DUCTORDER'. ...

Caused by: org.apache.derby.client.am.SqlException: The statement was aborted be-cause it would have caused a duplicate key value in a unique or primary key con-straint or unique index identified by 'SQL120513133540930' defined on 'PRODUCTOR-DER'.

Я не понимаю этого исключения. edit () работает отлично. НО я хотел бы добавить заказы продукта клиенту во время его создания, так что этого недостаточно.

Approach 2) merge() only

Изменения в Generic Persistence Facade:

// Called when pressing "save" on the "create new..." JSF page
public void create(T entity) {
    getEntityManager().merge(entity);
}

// Called when pressing "save" on the "edit..." JSF page
public void edit(T entity) {
    getEntityManager().merge(entity);
}

Результат:

При создании () вывод журнала EclipseLink сообщает:

Fine: INSERT INTO CLIENT (ID, NAME, ADDRESS_ID) VALUES (?, ?, ?) bind => [3 parameters bound]

но НЕТ "ОБНОВЛЕНИЯ" на столе заказа продукции. Таким образом, отношения не установлены. Опять же, edit (), с другой стороны, работает нормально.

Apporach 3) Id GenerationType.IDENTITY on both entity types

Изменения в классе заказа клиента и продукта:

...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...

Результат:

При создании () вывод журнала EclipseLink сообщает:

Fine: INSERT INTO CLIENT (NAME, ADDRESS_ID) VALUES (?, ?) bind => [2 parameters bound]

Fine: values IDENTITY_VAL_LOCAL()

Fine: INSERT INTO PRODUCTORDER (ORDERDATE, CLIENT_ID) VALUES (?, ?) bind => [2 parameters bound]

Fine: values IDENTITY_VAL_LOCAL()

таким образом, вместо установления отношения к заказу на продукт, добавленному в список клиента, создается и сохраняется новый объект заказа на продление (!) и устанавливается отношение к этому объекту. То же самое, edit () работает нормально.

Apporach 4) Подход (2) и (3) в сочетании

Результат: такой же, как подход (2).

Мой вопрос:Is there any way to realize the scenario described above? How can it be archieved? Я хотел бы остаться с JPA (нет решения для конкретного поставщика).

Ответы на вопрос(4)

Ваш ответ на вопрос