我正在使用Hibernate 4.3.6,并且我使用了最新的Maven bytecode enhancement来检测所有实体的自我肮脏意识。
我添加了maven插件:
<build>
<plugins>
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
我看到我的实体正在增强:
@Entity
public class EnhancedOrderLine
implements ManagedEntity, PersistentAttributeInterceptable, SelfDirtinessTracker
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private Long number;
private String orderedBy;
private Date orderedOn;
@Transient
private transient PersistentAttributeInterceptor $$_hibernate_attributeInterceptor;
@Transient
private transient Set $$_hibernate_tracker;
@Transient
private transient CollectionTracker $$_hibernate_collectionTracker;
@Transient
private transient EntityEntry $$_hibernate_entityEntryHolder;
@Transient
private transient ManagedEntity $$_hibernate_previousManagedEntity;
@Transient
private transient ManagedEntity $$_hibernate_nextManagedEntity;
...
调试时,我正在检查org.hibernate.event.internal.DefaultFlushEntityEventListener#dirtyCheck
方法:
if ( entity instanceof SelfDirtinessTracker ) {
if ( ( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes() ) {
dirtyProperties = persister.resolveAttributeIndexes( ( (SelfDirtinessTracker) entity ).$$_hibernate_getDirtyAttributes() );
}
}
并且$$_hibernate_hasDirtyAttributes()
始终返回 false 。
这是因为$$_hibernate_attributeInterceptor
始终为null,因此在设置任何属性时:
private void $$_hibernate_write_number(Long paramLong)
{
if (($$_hibernate_getInterceptor() == null) || ((this.number == null) || (this.number.equals(paramLong))))
break label39;
$$_hibernate_trackChange("number");
label39: Long localLong = paramLong;
if ($$_hibernate_getInterceptor() != null)
localLong = (Long)$$_hibernate_getInterceptor().writeObject(this, "number", this.number, paramLong);
this.number = localLong;
}
因为$$_hibernate_getInterceptor()
为null,所以将绕过trackChange,因此字节码增强不会解析脏属性,并且将使用默认的深度比较算法。
我错过了什么?如何正确设置$$_hibernate_attributeInterceptor
以便字节码检测方法跟踪脏属性?
答案 0 :(得分:3)
Hibernate 5 fixes this issue现在对setter的脏检查如下所示:
public void $$_hibernate_write_title(String paramString)
{
if (!EqualsHelper.areEqual(this.title, paramString)) {
$$_hibernate_trackChange("title");
}
this.title = paramString;
}
public void $$_hibernate_trackChange(String paramString)
{
if (this.$$_hibernate_tracker == null) {
this.$$_hibernate_tracker = new SimpleFieldTracker();
}
this.$$_hibernate_tracker.add(paramString);
}
因此,该解决方案是对Hibernate 5的升级。
答案 1 :(得分:2)
我不知道它是否能在所有情况下为您提供正确的行为,但您通常可以通过执行以下操作来检查脏检查(至少根据我测试过的一些框架代码): / p>
@EntityListeners(YourListener.class)
来注册实体侦听器@Pre
/ @Post
(例如@PrePersist
等)方法的实施方案添加到YourListener.class
,在那里检查实体是否是PersistentAttributeInterceptable
的实例,如果仅使用自定义$$_hibernate_setInterceptor
调用PersistentAttributeInterceptor
,只返回新值(特定行为可能需要经过精炼才能用于一般用途,我不确定,但它是足够好以便为我的简单测试捕获它 - 你知道更多关于拦截器的一般用例而不是我。)一个黑客解决方案,显然是一个错误。