我正在使用@Version注释在hibernate中提供版本控制。我的问题是关于数据从 DTO 到实体的正确映射。 我觉得正确的方法如下,但我想知道是否有更好的方法或者每个人都是这样做的。
- 调用来找我的服务
- 我加载要更新的实体(假设 AddressEntity 的版本 = 1)
- 我将 AddressDTO 值映射到 AE,包括子集合(如果有)
- 完成映射后,我分离实体 AE(仅在惰性子集合映射后才分离)
- 现在我将版本从 DTO 映射到 AE(因为 hibernate 不允许更新托管实体中的版本)
- 现在我调用 merge 来更新这个分离的 AE 实体
1)从语义和逻辑角度来说,这是正确的方式吗?
2)(有点脱离上下文) hibernate 合并已经在上下文中并托管的对象是否有开销,即我可以安全地使用合并来进行所有更新,无论托管/非托管还是仅合并+刷新用于非托管并刷新更新一些属性后进行管理?
最佳答案
让我尝试逐步回答您的问题:
- 假设您已加载
AddressEntity (having id=123 and version=1)
。设置属性值AddressEntity
至AddreeDto
包括id
和version
值(value)观。发送AddressDto
到用户界面。 - 对
AddresDto
进行的更改。已调用为您服务。创建AddressEntity
的实例并设置AddressDto
中的值包括id
和version
值(value)观。这个新AddressEntity
现在已变成分离实例,因为它具有持久标识,但不能保证其状态与数据库状态同步。 Hibernate 允许您重用此
Addressentity
通过将实例与新的持久性管理器重新关联,可以将其重新关联到新事务中。可以通过调用 update() 将该分离的实例与新 session 重新关联。您不需要再次加载实体。update()方法强制更新数据库中对象的持久状态。设置
addressEntity
属性:addressEntity.setId(dto.getId()); addressEntity.setVersion(dto.getVersion());
附加
addressEntity
到新 session :交易 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
。您可以捕获异常并通知用户有关过时数据的信息。
关于java - 使用 hibernate @Version 控制进行 DTO 实体映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18731516/