JPA @Version行为

时间:2011-03-10 10:48:34

标签: hibernate jpa jpa-2.0

我正在使用JPA2和Hibernate 3.6.x

我在@Version上做了一个简单的测试。

假设我们有2个实体,

  1. 实体团队有一个玩家实体列表,双向关系,懒惰fetchtype,级联类型全部
  2. 两个实体都有@Version
  3. 以下是情景:

    1. 每当对团队/玩家实体之一进行修改时,团队/玩家的版本将在刷新/提交时增加(修改后的记录上的版本增加)。

    2. 使用persist将新的玩家实体添加到团队的集合中,该团队的版本将在持久化后被分配(添加新实体,新实体将获得它的版本)。

    3. 每当对其中一个玩家实体进行添加/修改/删除时,团队的版本将在刷新/提交时增加。 (添加/修改/删除子记录,父版本也增加了)

    4. 我能理解数字1和2,但数字3,我不明白,为什么团队的版本增加了?

      这让我想到了其他问题:

      1. 如果我有父母< - >该怎么办?孩子< - > granchildren关系船。孙子孙女的增加或修改会增加孩子和父母的版本吗?
      2. 在方案2中,如何在提交之前获得团队版本,例如使用flush?在我们对孩子做某事之后,这是一种推荐的获得父母版本的方法吗?

      3. 这是我实验的代码示例,证明当ReceivingGoodDetail是拥有方时,刷新后ReceivingGood中的版本增加了。很抱歉,这使用其他实体,但ReceivingGood就像团队一样,ReceivingGoodDetail就像玩家一样。 1接收良好/团队,许多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 个答案:

答案 0 :(得分:13)

它看起来像是Hibernate中的一个错误。

JPA规范说:

  

所有非关系字段和属性以及实体拥有的所有关系都是   包含在版本检查中

但是,Hibernate也会在更改非拥有关系属性后增加版本(例如,EclipseLink不会这样做)。可以通过在属性上设置@OptimisticLock(exclude = true)来禁用此行为。

请注意,它仅适用于关系属性本身的更改,而不适用于引用对象状态的更改,因此父级版本不会因孙子集合的更改而发生更改。 / p>