【发布时间】:2011-07-12 15:06:31
【问题描述】:
我在 Hibernate 3.6.x 中使用 JPA2
我对@Version做了一个简单的测试。
假设我们有 2 个实体,
- Entity Team 有一个 Player Entities 列表,双向关系,lazy fetchtype,cascade-type All
- 两个实体都有@Version
这里是场景:
每当对团队/玩家实体之一进行修改时,刷新/提交时团队/玩家的版本将增加(修改记录上的版本增加)。
使用persist将新的玩家实体添加到团队的集合中,将在persist后分配团队版本的实体(添加新实体,新实体将获得它的版本)。
每当对玩家实体之一进行添加/修改/删除时,刷新/提交时团队的版本将增加。 (添加/修改/删除子记录,父版本也增加了)
1号和2号我能看懂,但是3号我就不明白了,为什么团队的版本变高了?
这让我想到了其他问题:
- 如果我得到了父 子 孙关系船怎么办。对孙子的添加或修改会增加子代和父代的版本吗?
- 在场景号 2 中,我如何在团队提交之前获得版本,比如使用 flush ?在我们对孩子做了一些事情之后,是否推荐使用这种方式来获取父母的版本?
这是我实验的代码示例,证明当 ReceivingGoodDetail 是拥有方时,刷新后 ReceivingGood 中的版本增加了。抱歉,这使用了其他实体,但 ReceivingGood 就像 Team,ReceivingGoodDetail 就像 Player。 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());
}
【问题讨论】:
-
关系的拥有方是哪一方?球员还是球队?
-
我只是假设“拥有方”一词是指拥有实体集合的一方。 Team 与 Player 有一对多的关系。所以我认为这意味着团队是拥有方,因为它拥有一群球员。
-
简而言之,拥有方是您主动更改的部分。基本上,“一个人有很多书”,而不是“一本书有很多人”。在您的情况下,“团队由玩家组成”。所以,你会改变一个球员的球队,而不是球队的球员(player.setTeam() 而不是 team.getPlayers()...setTeam())
-
顺便说一句:axtavt 实际上回答了你的问题。我相信他也认为拥有方是玩家。
-
@partenon:谢谢你的解释。明天将在我的办公室电脑上再次检查我的测试代码。我的代码围绕着从EM中获取玩家实体,然后修改玩家实体中的一些属性,然后利用team.addPlayer(player),其主要过程基本上是删除集合中存在的玩家,并添加它又来收藏了,还设置了玩家的队伍。也许我真的不需要再次将其添加到列表中以避免团队记录中的版本增加,考虑到当我从 EM 获得玩家实体时,它已经被管理了。