Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate 4 bytecode enhancement not working for dirty checking optimization

I am using the Hibernate 4.3.6 and I made use of the latest Maven bytecode enhancement to instrument all entities for self dirtiness awareness.

I added the maven plugin:

<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> 

and I see my entities are being enhanced:

@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;    ... 

While debugging, I am checking org.hibernate.event.internal.DefaultFlushEntityEventListener#dirtyCheck method:

        if ( entity instanceof SelfDirtinessTracker ) {             if ( ( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes() ) {                 dirtyProperties = persister.resolveAttributeIndexes( ( (SelfDirtinessTracker) entity ).$$_hibernate_getDirtyAttributes() );             }         } 

and the $$_hibernate_hasDirtyAttributes() always returns false.

This is because $$_hibernate_attributeInterceptor is always null, so when setting any property:

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; } 

because the $$_hibernate_getInterceptor() is null the trackChange will be bypassed, hence the bytecode enhancement will not resolve the dirty properties and the default deep-comparison algorithm will be used.

What am I missing? How can I get the $$_hibernate_attributeInterceptor to be properly set so that the dirty properties are tracked by the bytecode instrumentation methods?

like image 460
Vlad Mihalcea Avatar asked Sep 06 '14 16:09

Vlad Mihalcea


1 Answers

Hibernate 5 fixes this issue and now the dirty checking for a setter looks like this:

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); } 

So, the solution is an upgrade to Hibernate 5.

like image 140
Vlad Mihalcea Avatar answered Oct 05 '22 15:10

Vlad Mihalcea