Среда гибернации: аудит поля @CollectionTable

#java #hibernate #hibernate-envers

#java #переход в спящий режим #hibernate-envers

Вопрос:

Я пытаюсь провести аудит Order класса, у которого есть List<OrderItem> поле. Order Класс выглядит следующим образом:

 class Order {
    @Audited
    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "order_order_item", joinColumns = @JoinColumn(name = "order_id"))
    List<OrderItem> items;
}
  

И для OrderItem класса выглядит так:

 class OrderItem {
    private Integer quantity;
    private Long itemId;
}
  

Каждый заказ должен содержать уникальный элемент OrderItem (различать по ItemId).

Проблема в том, что я пытаюсь создать Order , который имеет несколько OrderItem s, каждый элемент уникален, но в исключении hibernate throw указано:

 A different object with the same identifier value was already associated with the session : [order_order_item_AUD#{SETORDINAL=1, REV=DefaultRevisionEntity(id = 16, revisionDate = Oct 9, 2016 1:38:12 PM), Order_id=57, REVTYPE=ADD}]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [order_order_item_AUD#{SETORDINAL=1, REV=DefaultRevisionEntity(id = 16, revisionDate = Oct 9, 2016 1:38:12 PM), Order_id=57, REVTYPE=ADD}]
  

Я думаю, что проблема, вероятно, заключается в том, что envers используют один и тот же идентификатор для разных OrderItem , потому что envers видят только order_id из @JoinColumn и обрабатывают его как идентификатор.

Я не знаю, как сказать envers использовать оба itemId и order_id в качестве идентификатора ревизии, или, может быть, я неправильно понимаю проблему.

Пожалуйста, помогите.

Спасибо.

Комментарии:

1. итак, первичный ключ в вашем случае состоит из ItemId и order_id?

2. Из приведенных мною определений классов явно не задано, чтобы первичный ключ состоял из ItemId и order_id, потому что у меня нет order_id внутри OrderItem определения, но я могу создать уникальное ограничение в СУБД, чтобы убедиться в этом.

3. Насколько я понимаю, я думаю, что @ElementCollection это также не заботится о первичном ключе, он просто извлекает / объединяет элементы из @CollectionTable использования @JoinColumn в качестве точки соединения.

4. «скажите hibernate использовать как ItemId, так и order_id в качестве идентификатора» что вы пытаетесь определить, почему вы даже используете таблицу коллекции здесь? насколько я понимаю, вам нужна объединяемая таблица, а не таблица коллекции

5. @AmerQarabsa Спасибо, я пытаюсь выполнить ваше предложение. Я буду обновлять об этом.

Ответ №1:

Вместо этого вы можете рассмотреть возможность отображения этого следующим образом:

 @Embeddable
public class OrderItemId implements Serializable {
  private Long orderId;

  private Long itemId;
}

@Entity
public class OrderItem {
  @EmbeddedId
  private OrderItemId id;

  @ManyToOne
  @MapsId("orderId")
  @JoinColumn(name = "order_id")
  private Order order;

  @ManyToOne
  @MapsId("itemId")
  @JoinColumn(name = "item_id")
  private Item item;
}
  

Если вы хотите сохранить @ElementCollection сопоставление, вам может потребоваться включить @OrderColumn аннотацию и убедиться, что вы реализуете правильные методы hashCode / equals, которые используют только значения item_id и order_id .