我正在使用@Version注释在休眠中提供版本控制。我的问题是关于从DTO到实体的数据正确映射。
我认为正确的方法如下,但是我想知道是否有更好的方法,或者这是每个人的方法。


来电来我服务
我加载要更新的实体(假设AddressEntity版本为1)
我将AddressDTO值映射到AE,包括子集合(如果有)
毕竟映射后,我分离了实体AE(也仅在映射了惰性子集合后才分离)
现在我将版本从DTO映射到AE(因为休眠不允许更新托管实体中的版本)
现在我打电话给merge来更新这个独立的AE实体


1)这是正确的语义和逻辑方法吗?

2)(脱离上下文)有没有休眠的开销来合并已经存在于上下文中的对象和托管对象,即我是否可以安全地使用合并进行所有更新,而不论托管还是托管/非托管,或者仅合并+刷新表示非托管,而刷新则表示托管后进行更新一些属性?

最佳答案

让我尝试逐步回答您的问题:


假设您已加载AddressEntity (having id=123 and version=1)。将属性值从AddressEntity设置为AddreeDto,包括idversion值。将AddressDto发送到UI。
AddresDto所做的更改。来电已为您服务。创建AddressEntity的实例,并设置AddressDto中的值,包括idversion值。这个新的AddressEntity现在具有持久的标识,但现在已变成一个分离的实例,但是不能保证其状态与数据库状态同步。
Hibernate通过与新的持久性管理器重新关联,使您可以在新事务中重用此Addressentity实例。可以通过调用update()将此分离的实例与新的Session重新关联。您无需再次加载实体。update()方法将更新强制为数据库中对象的持久状态。

设置addressEntity属性:

addressEntity.setId(dto.getId());
addressEntity.setVersion(dto.getVersion());

addressEntity附加到新会话:

交易tx = sessionTwo.beginTransaction();
sessionTwo.update(addressEntity);

tx.commit();
sessionTwo.close();
session.update将执行与此类似的SQL:

更新ADDRESS_ENTITY设置...,VERSION = 2
其中ID = 123和VERSION = 1
如果另一个应用程序事务自加载以来已经更新了相同的ADDRESS_ENTITY,则VERSION列将不包含值1,并且该行也不会被更新,并且您将收到stale object state exception。您可以捕获异常并将过时的数据通知用户。

09-25 22:31