Как заполнить дочерний составной ключ из значения родительской последовательности (Hibernate, JPA)?

У меня есть ситуация, когда у меня есть класс Called Order со сгенерированным OrderID:

    @Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_gen")
@SequenceGenerator(name = "seq_gen", sequenceName = "OID_SEQ1")
@Column(name = "ORDER_ID",nullable = false)
public long getOrderId()
{
    return this.OrderId;
}

он также имеет сопоставление «один ко многим» с классом/таблицей, называемой элементами:

    @OneToMany(fetch = FetchType.LAZY,mappedBy = "orders",targetEntity = Items.class)
public Set<Items> getItems()
{
    return this.items;
}

внутри класса элементов есть встроенный/составной идентификатор:

    @EmbeddedId
@AttributeOverrides({@AttributeOverride(name = "OrderId",column = @Column(name = "ORDER_ID",nullable = false)),
        @AttributeOverride(name = "role",column = @Column(name = "ROLE",nullable = false,length = 10))})
public ItemId getId()
{
    return this.id;
}

Моя проблема заключается в том, что часть этого идентификатора является первичным ключом родительского класса Order.class. Другими словами, значение последовательности. Это означает, что я не могу установить это значение где угодно, и когда я звоню:

entitymanager.persist(order);

Родительский объект Order записывает в базу данных, НО ни один из элементов в наборе не сохраняется. Существует только один оператор вставки, и все ссылки на orderId в объектах Items равны нулю????

Как я могу заполнить эти идентификаторы сгенерированным идентификатором Seq?

Большое спасибо за любую помощь в этом!


person Michael W    schedule 21.10.2011    source источник


Ответы (2)


В конце концов понял это с помощью другого сообщения: onetomany-and-composite-primary-keys Ответ был на самом деле довольно прост. Нам нужно использовать аннотацию Casade, чтобы каскадировать Id до дочернего объекта. поэтому приведенное выше сопоставление «один ко многим» становится:

@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy = "orders",targetEntity = Items.class) public Set<Items> getItems() {     return this.items; } 

При реализации этого обзора различные типы каскадов.

Удачи

person Michael W    schedule 28.10.2011

Я не уверен на 100%, основываясь на вашем вопросе, но я думаю, что вы ищете EntityManager.flush():

// Create an Order with no items, get its order ID
Order order = new Order(...);
em.persist(order);
// Order should have the generated ID filled in after this call to flush()
em.flush();  

// Create all the items for an order, filling in the Order ID into each item's
// composite key
for(...) {
    // create new item
    Item item = new Item(...);
    // populate other parts of the Item's composite key here
    // then fill in the OrderID part of the composite key
    item.getId().setOrderId(order.getOrderId());
    // add new item to the order's collection
    order.addItem(item);
}

Вам не нужен еще один вызов persist() после заполнения элементов.

person BobG    schedule 26.10.2011
comment
Привет большое спасибо за ответ. К сожалению, это не сработало. Я никогда не шел по этому пути, так как мне посоветовали, что сброс - это операция, которой следует избегать. - person Michael W; 28.10.2011
comment
Интересный. На самом деле я использую JPA 2 с Hibernate в качестве провайдера в одном из моих проектов, и мой ПК заполняется, как только я выдаю em.persist() - мне даже не нужен em.flush(). Я использую Postgres для серверной части — может быть, серверная часть базы данных влияет на генерацию PK? - person BobG; 03.11.2011