【发布时间】:2017-03-03 14:46:39
【问题描述】:
我现在有点困惑。我会尽量简单地解释我的担忧:
我有一个 Spring Boot 应用程序,当然,它有实体。这些实体通过百里香叶形式更新。在这种形式中,只有一些相关字段是可更改的。例如实体的name。 created、createdby 或 lastUsedBy 等其他字段不受此表单的控制/更改。
现在问题来了:如果我们现在更改实体,所有其他字段都设置为null,因为它们不在请求中。一种方法是为这些缺失的字段添加<input type="hidden"/>inputs。但这不是很优雅且容易出错。
比我得出的结论,休眠应该只更新那些已更改的字段。所以这必须通过 DirtyTracking 来完成。我目前有另一个应用程序,它使用 OpenJPA 和 openJPA 增强器,在这个应用程序中,更新只更新更改的字段。我的假设是 Hibernate 增强器可以解决我的问题。但是即使启用了脏跟踪,所有字段都会更新并且信息会丢失。
当我将@DynamicUpdateannotation 添加到给定实体时,我已经设法让它工作,但这不是正确的方法吗?
我仔细检查了实体是否得到了增强,还调试了 spring/hibernate 的整个保存过程。我在这里错过了什么吗?为什么休眠还会更新所有非脏字段?
编辑
我进一步检查并得出这一点:代码来自 AbstractEntityTuplizer
public void setPropertyValues(Object entity, Object[] values) throws HibernateException {
boolean setAll = !entityMetamodel.hasLazyProperties();
for ( int j = 0; j < entityMetamodel.getPropertySpan(); j++ ) {
if ( setAll || values[j] != LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
setters[j].set( entity, values[j], getFactory() );
}
}
}
values 对象数组只有几个预填充的值,只有更改/脏的值。例如values[5] 和values[6]。但是所有的设置器都会被调用,并且如果它们没有出现在函数的值参数中,它们的值将设置为null。对我来说看起来像是一个错误。
【问题讨论】:
-
FWIW DataNucleus JPA 也使用字节码增强,增强合约将跟踪字段何时变脏(只需查看反编译的增强类了解如何),因此只会更新需要更新的字段。它使用的字节码增强合约源自 JDO 规范(OpenJPA 多年前也从该规范派生)
标签: java spring hibernate jpa byte-code-enhancement