当前位置: 首页 > 面试题库 >

JPA @Version行为

岑俊明
2023-03-14
问题内容

我在Hibernate 3.6.x中使用JPA2

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

假设我们有2个实体,

  1. 实体团队具有玩家实体列表,双向关系,惰性获取类型,级联类型全部
  2. 两个实体都有@Version

这是场景:

  1. 每当对团队/球员实体之一进行修改时,刷新/提交时,团队/球员的版本就会增加(修改后的记录的版本会增加)。

  2. 使用persist将新的球员实体添加到团队的集合中,将在persist之后分配团队版本的实体(添加新实体,该新实体将获取其版本)。

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

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

这让我想到了其他问题:

  1. 如果我得到了父母<->儿童<->亲子关系船该怎么办。对子孙的增加或修改会增加孩子和父母的版本吗?
  2. 在场景2中,如何在提交之前在团队中获取版本,例如使用flush?在对孩子做一些事情之后,是否建议获取父母的版本?

这是来自我的实验的代码示例,证明当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.html" target="_blank">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规范说:

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

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

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



 类似资料:
  • 问题内容: 批注在JPA中如何工作? 我找到了各种答案,摘录如下: JPA使用实体中的版本字段来检测对同一数据存储记录的并发修改。当JPA运行时检测到尝试同时修改同一记录的尝试时,它将向尝试最后提交的事务抛出异常。 但是我仍然不确定它是如何工作的。 同样从以下几行开始: 您应该考虑版本字段是不变的。更改字段值会产生不确定的结果。 这是否意味着我们应该将version字段声明为? 问题答案: 但是我

  • 问题内容: 是否需要为创建setter / getter ? 当使用Hibernate持久化该实体时,我不需要手动设置此值,对吗? 为了在Spring的服务器上使用乐观并发检查,我还需要配置什么?是否支持所有数据库? 如何对该实体进行单元测试?在我的数据库中,所有显示版本字段的记录的值为0 每次调用都会增加版本值吗? 问题答案: 我会说: 必须设置/获取版本,因为有时您可能自己分配版本(从旧数据重

  • 问题内容: 我是JPA和Hibernate的新手,我对乐观锁定有疑问。我有一个拥有@Version注释字段的类。当我更新此类所代表的实体时,版本计数器不会增加。这是我的代码:该类: 这是主要方法: 控制台的内容如下: 有人可以告诉我怎么了吗? 编辑: 好的,我尝试了一些。我已将锁定设置为LockModeType.OPTIMISTIC_FORCE_INCREMENT并收到以下错误消息: 因此,很明显

  • 签名 m.version 参数 类型 是否必须 描述 返回 String 返回版本号 工作原理 m.version 属性会返回当前 Mithril 的版本号。 版本号使用 semver 规范,格式为 “0.0.0”,第一个数字是主板本号,第二个数字是次版本好,第三个数字是修订版本号。 当有向下不兼容的 API 更改时,更新主版本号 当添加新功能,且向下兼容时,更新次版本号 当修复 bug,且向下兼

  • 返回当前 Rax core 的版本。 API version: string 示例 import { version } from 'rax'; console.log('version: ', version); // ==> version: 1.0.4

  • 藐视: 描述版本信息。 概述 @version标签后面的文本将被用于表示该项的版本。 例子 例如,使用@version标签: /** * Solves equations of the form a * x = b. Returns the value * of x. * @version 1.2.3 * @tutorial solver */ function solver(a, b