JPA @ Версия поведения - PullRequest
       1

JPA @ Версия поведения

10 голосов
/ 10 марта 2011

я использую JPA2 с Hibernate 3.6.x

Я провел простое тестирование на @ Version.

Допустим, у нас есть 2 сущности,

  1. У Entity Team есть список игроков, двунаправленные отношения, ленивый тип извлечения, каскадный тип Все
  2. Оба объекта имеют @ Version

И вот сценарии:

  1. Всякий раз, когда вносится изменение в одну из сущностей команды / игрока, версия команды / игрока увеличивается при очистке / фиксации (версия на измененной записи увеличивается).

  2. Добавление новой сущности игрока в коллекцию команды с помощью persist, сущность, которой будет присвоена версия команды после сохранения (добавление новой сущности, эта новая сущность получит свою версию).

  3. Всякий раз, когда добавляется / модифицируется / удаляется один из объектов игрока, версия команды будет увеличена при сбросе / подтверждении.(добавить / изменить / удалить дочернюю запись, версия для родителей также увеличилась)

Я могу понять цифры 1 и 2, но номер 3, я не понимаю, почему версия команды получилаувеличился?

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

  1. Что если я получу корабль отношений между родителями <-> child <-> granchildren.Будет ли добавление или модификация внуков увеличивать версию child и parent?
  2. В сценарии № 2, как я могу получить версию в команде до ее принятия, например, используя flush?Это рекомендуемый способ получить версию родителя после того, как мы что-то сделаем с ребенком?

Вот пример кода из моего эксперимента, доказывающий, что когда ReceivingGoodDetail является владельцем,и версия была увеличена в ReceivingGood после сброса.Извините, что для этого используются другие сущности, но ReceivingGood - это как команда, ReceivingGoodDetail - как игрок.1 ReceivingGood / Team, многие ReceivingGoodDetail / Player.

/*
Hibernate: select receivingg0_.id as id9_14_, receivingg0_.creationDate as creation2_9_14_, .. too long
Hibernate: select product0_.id as id0_4_, product0_.creationDate as creation2_0_4_, .. too long
before persisting the new detail, version of header is : 14
persisting the detail 1c9f81e1-8a49-4189-83f5-4484508e71a7
printing the size of the header : 
Hibernate: select details0_.receivinggood_id as receivi13_9_8_, details0_.id as id8_, details0_.id as id10_7_, .. too long
7
after persisting the new detail, version of header is : 14
Hibernate: insert into ReceivingGoodDetail (creationDate, modificationDate, usercreate_id, usermodify_id, version, buyQuantity, buyUnit, internalQuantity, internalUnit, product_id, receivinggood_id, supplierLotNumber, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: update ReceivingGood set creationDate=?, modificationDate=?, usercreate_id=?, usermodify_id=?, version=?, purchaseorder_id=?, supplier_id=?, transactionDate=?, transactionNumber=?, transactionType=?, transactionYearMonth=?, warehouse_id=? where id=? and version=?
after flushing, version of header is now : 15
    */
public void addDetailWithoutTouchingCollection() {
    String headerId = "3b373f6a-9cd1-4c9c-9d46-240de37f6b0f";
    ReceivingGood receivingGood = em.find(ReceivingGood.class, headerId);

    // create a new detail
    ReceivingGoodDetail receivingGoodDetailCumi = new ReceivingGoodDetail();
    receivingGoodDetailCumi.setBuyUnit("Drum");
    receivingGoodDetailCumi.setBuyQuantity(1L);
    receivingGoodDetailCumi.setInternalUnit("Liter");
    receivingGoodDetailCumi.setInternalQuantity(10L);
    receivingGoodDetailCumi.setProduct(getProduct("b3e83b2c-d27b-4572-bf8d-ac32f6de5eaa"));
    receivingGoodDetailCumi.setSupplierLotNumber("Supplier Lot 1");
    decorateEntity(receivingGoodDetailCumi, getUser("3978fee3-9690-4377-84bd-9fb05928a6fc"));
    receivingGoodDetailCumi.setReceivingGood(receivingGood);

    System.out.println("before persisting the new detail, version of header is : " + receivingGood.getVersion());

    // persist it
    System.out.println("persisting the detail " + receivingGoodDetailCumi.getId());
    em.persist(receivingGoodDetailCumi);

    System.out.println("printing the size of the header : ");
    System.out.println(receivingGood.getDetails().size());

    System.out.println("after persisting the new detail, version of header is : " + receivingGood.getVersion());

    em.flush();

    System.out.println("after flushing, version of header is now : " + receivingGood.getVersion());
}

1 Ответ

13 голосов
/ 10 марта 2011

Это похоже на ошибку в Hibernate.

Спецификация JPA гласит:

Все несвязанные поля и свойства, а также все отношения, принадлежащие сущности, включаются в проверки версий

Однако Hibernate также увеличивает версию после изменения не принадлежащих ей свойств отношений (тогда как, например, EclipseLink этого не делает).Это поведение можно отключить, установив @OptimisticLock(exclude = true) в свойстве.

Обратите внимание, что оно применимо только к изменениям самого свойства отношения, а не к изменениям состояния ссылочных объектов, так что версия parent не будетбыть изменения из-за изменений в коллекции внуков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...