我正在使用@Version注释在休眠中提供版本控制。我的问题是关于从DTO到实体的数据正确映射。
我认为正确的方法如下,但是我想知道是否有更好的方法,或者这是每个人的方法。
来电来我服务
我加载要更新的实体(假设AddressEntity版本为1)
我将AddressDTO值映射到AE,包括子集合(如果有)
毕竟映射后,我分离了实体AE(也仅在映射了惰性子集合后才分离)
现在我将版本从DTO映射到AE(因为休眠不允许更新托管实体中的版本)
现在我打电话给merge来更新这个独立的AE实体
1)这是正确的语义和逻辑方法吗?
2)(脱离上下文)有没有休眠的开销来合并已经存在于上下文中的对象和托管对象,即我是否可以安全地使用合并进行所有更新,而不论托管还是托管/非托管,或者仅合并+刷新表示非托管,而刷新则表示托管后进行更新一些属性?
最佳答案
让我尝试逐步回答您的问题:
假设您已加载AddressEntity (having id=123 and version=1)
。将属性值从AddressEntity
设置为AddreeDto
,包括id
和version
值。将AddressDto
发送到UI。
对AddresDto
所做的更改。来电已为您服务。创建AddressEntity
的实例,并设置AddressDto
中的值,包括id
和version
值。这个新的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
。您可以捕获异常并将过时的数据通知用户。