gpt4 book ai didi

hibernate - 合并并获取未刷新的待更新版本?

转载 作者:行者123 更新时间:2023-12-03 14:12:32 25 4
gpt4 key购买 nike

是否可以在不使用冲洗的情况下更改版本化的实体实例并获得要递增的版本?因为从我所读的内容来看,恐怕刷新不是一个好习惯,因为它会对性能甚至数据损坏产生不良影响?我不确定:D

这是一个简单的代码,也将输出作为注释:

/*
Hibernate: select receivingg0_.id as id9_14_, receivingg0_.creationDate as creation2_9_14_, ... too long
the version before modification : 16
the version after modification : 16
after merge the modification, the version is : 16
Hibernate: update ReceivingGood set creationDate=?, modificationDate=?, usercreate_id=?, usermodify_id=?, ... too long
after flushing the modification, the version is finally : 17
*/
public void modifyHeaderAndGetUpdatedVersion() {
String id = "3b373f6a-9cd1-4c9c-9d46-240de37f6b0f";
ReceivingGood receivingGood = em.find(ReceivingGood.class, id);
System.out.println("the version before modification : " + receivingGood.getVersion());

receivingGood.setTransactionNumber("NUM001xyz");
System.out.println("the version after modification : " + receivingGood.getVersion());

receivingGood = em.merge(receivingGood);
System.out.println("after merge the modification, the version is : " + receivingGood.getVersion());

em.flush();
System.out.println("after flushing the modification, the version is finally : " + receivingGood.getVersion());
}

在我的测试中,刷新后版本增加了。从合并操作返回的实例没有递增版本。

但就我而言,我想以DTO形式将实体返回到我的Webui,并且在将实体转换为DTO并将其返回到要呈现的UI之前,该实体应该具有刷新后/提交后的版本。然后,UI可能具有最新版本,并将在下一次提交时传递此版本。

有什么办法可以不用冲洗就可以获取最新版本?

谢谢 !

更新

根据我的经验,从下面的示例可以看出,手动增加该值可能会遇到问题。在此示例中,我们有2次刷新。

第一个是将对db连接的更改同步,以便来自同一连接的存储过程调用可以看到来自entityManager所做的更改。

调用第二次冲洗以获取最终版本。我们可以看到 增加了两倍。因此在这种情况下,仅从手动增量中获取版本而不进行刷新将不会起作用,因为我们必须真正计算正在执行多少次刷新。
/*
Hibernate: select receivingg0_.id as id9_14_, receivingg0_.creationDate as creation2_9_14_, .. too long
the version before modification : 18
the version after modification : 18
after merge the modification, the version is : 18
now flushing the modification, so that the stored procedure call from the same connection can see the changes
Hibernate: update ReceivingGood set creationDate=?, modificationDate=?, usercreate_id=?, .. too long
after flushing the modification, the version is : 19
Hibernate: update ReceivingGood set creationDate=?, modificationDate=?, usercreate_id=?, .. too long
after the second flush, the version got increased again into : 20
*/
public void modifyHeaderAndGetUpdatedVersionWith2Flushes() {
String id = "3b373f6a-9cd1-4c9c-9d46-240de37f6b0f";
ReceivingGood receivingGood = em.find(ReceivingGood.class, id);
System.out.println("the version before modification : " + receivingGood.getVersion());

//auditEntity(receivingGood, getUser("3978fee3-9690-4377-84bd-9fb05928a6fc"));
receivingGood.setTransactionNumber("NUM001xyz");
System.out.println("the version after modification : " + receivingGood.getVersion());

receivingGood = em.merge(receivingGood);
System.out.println("after merge the modification, the version is : " + receivingGood.getVersion());
System.out.println("now flushing the modification, so that the stored procedure call from the same connection can see the changes");
em.flush();
System.out.println("after flushing the modification, the version is : " + receivingGood.getVersion());

receivingGood.setTransactionNumber("NUM001abc");

em.flush();
System.out.println("after the second flush, the version got increased again into : " + receivingGood.getVersion());
}

这是否意味着我真的必须依靠最后的刷新来获取修改后的实体的最新版本?

更新2

这是一个服务方法的简单示例,该服务方法将更新ReceivingGood实体并应返回具有最新版本的DTO。
public ReceivingGoodDTO update(ReceivingGood entity) {
// merge it
entity = entityManager.merge(entity);

// the version is not incremented yet, so do the flush to increment the version
entityManager.flush(); // if i dont do this, the dto below will get the unincremented one

// use a mapper, maybe like dozer, to copy the properties from the entity to the dto object, including the newest version of that entity
ReceivingGoodDTO dto = mapper.map(entity, dto);

return dto;
}

这是一个使用该方法的示例:
@Transactional
public ReceivingGoodDTO doSomethingInTheServiceAndReturnDTO() {
// do xxx ..
// do yyy ..
dto = update(entity);
return dto; // and the transaction commits here, but dto's version isnt increased because it's not a managed entity, just a plain POJO
}

最佳答案

我将再次建议阅读有关Hibernate及其工作方式的更多信息,无论是其文档还是“带有Hibernate的Java持久性”。

您会在刷新操作中看到此消息,因为这是数据库更新发生的地方。如果只是省略刷新并提交事务,您将看到相同的行为。这意味着,每当您的工作单元完成时,Hibernate都会将更改刷新到数据库中。在此步骤中,Hibernate会比较并更新版本号。如果数据库版本为17,而您正在更新版本16,则Hibernate将引发有关更新陈旧对象的异常。

也就是说,您可以通过在实例中当前拥有的值上增加1来“预测”下一版本。但这将永远是不现实的,因为只有在更新数据库记录之前才有效地对其进行递增。因此,除非查询数据库,否则所有并发的更改对您的线程都是不可见的。

编辑:

您看到两个增量,因为您要进行两次冲洗。 “版本”是一种用于“乐观”锁定的技术,这意味着,您希望在任何工作单元期间只有一个线程将更新一条记录(从广义上讲,它被认为是“用户操作”,其中列出了记录,选择一个并进行更新)。目的主要是为了避免Hibernate更新过时的对象,在该对象中,两个用户选择同一条记录进行编辑,进行一些并发更改并更新它。其中一项编辑将被拒绝,并且第一个击中数据库的文件将获胜。当您两次更新记录(通过两次调用刷新)时,您看到两个增量。但这实际上与刷新无关,而与“数据库中发布的更新”有关。如果您有两次交易,您将看到相同的行为。

也就是说,值得注意的是,该技术应由Hibernate管理。您不应该自己增加它。不提供此类领域的设置方法通常是一个好习惯。

换句话说:您应将“版本”视为只读值,并且无法对其进行控制。因此,在屏幕上为用户显示其值是安全的,但是操纵它(或“确定”下一个版本)是不安全的。最多,您可以进行一次“最佳猜测”,预测它将为current_version + 1。

关于hibernate - 合并并获取未刷新的待更新版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5270720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com