hibernate - JPA @Version行为

标签 hibernate jpa jpa-2.0

即时通讯与Hibernate 3.6.x一起使用JPA2

我已经对@Version进行了简单的测试。

假设我们有2个实体,

  • 实体团队拥有玩家实体列表,双向关系,延迟获取类型,级联类型所有
  • 两个实体都有@Version

  • 这是场景:
  • 每当对团队/球员实体之一进行修改时,刷新/提交时,团队/球员的版本都会增加(修改记录的版本会增加)。
  • 使用persist将新的玩家实体添加到团队的集合中,在persist之后将分配团队版本的实体(添加一个新实体,该新实体将获取其版本)。
  • 每当对一个玩家实体进行添加/修改/删除时,刷新/提交时团队的版本将增加。 (添加/修改/删除 child 的记录, parent 的版本也增加了)

  • 我可以理解数字1和2,但是我不能理解数字3,为什么团队的版本增加了?

    这让我想到了其他问题:
  • 如果我得到了 parent <-> child <->亲子关系船该怎么办。对子孙的增加或修改会增加 child 和 parent 的版本吗?
  • 在方案2中,如何在提交之前在团队中获取版本,例如使用flush?在对 child 做一些事情之后,是否建议获取 parent 的版本?


  • 这是来自我的实验的代码示例,证明当ReceivingGoodDetail是拥有方时,刷新后版本在ReceivingGood中得到了增加。抱歉,这使用其他实体,但是ReceivingGood像Team,ReceivingGoodDetail像Player。 1个ReceivevingGood/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());
    }
    

    最佳答案

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

    JPA规范说:

    All non-relationship fields and properties and all relationships owned by the entity are included in version checks



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

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

    关于hibernate - JPA @Version行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5258585/

    相关文章:

    java - hibernate 如何决定默认使用哪个 FetchMode?

    java - 使用 jpa2 和 hibernate 3.6.x 的生产实例的示例 persistence.xml

    java - 让 Hibernate 在完成实体实例后释放它们?

    java - 用于 HSQLDB 的 Hibernate @generatedvalue

    java - 参数值 [2] 与预期类型不匹配 [com.cityBike.app.model.User

    java - JPA EntityManager 无法在 PostInsertEventListener 中刷新

    java - JPQL 限额查询

    oracle - Hibernate 将两个属性映射到一列

    java - 如何构建标准化的 RESTful Java API

    java - 使用 JPA 和 JSF 保留连接表