我正在使用Hibernate 4.3.6,并且使用了最新的Maven字节码增强功能来检测所有实体是否具有自我污染意识。
我添加了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方法:
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_hasDirtyAttributes()
这是因为$$_hibernate_attributeInterceptor始终为null,因此在设置任何属性时:
$$_hibernate_attributeInterceptor
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_getInterceptor()
我想念什么?如何$$_hibernate_attributeInterceptor正确设置,以便字节码检测方法可以跟踪脏属性?
Hibernate 5解决了此问题,现在对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的升级。