簡體   English   中英

Hibernate 4字節碼增強功能不適用於臟檢查優化

[英]Hibernate 4 bytecode enhancement not working for dirty checking optimization

我正在使用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方法:

        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 ,以便字節碼檢測方法跟蹤臟屬性?

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。

我不知道它是否會在所有情況下都給你正確的行為,但你通常可以通過執行以下操作來使臟檢查工作(至少根據我測試過的一些框架代碼):

  1. 通過將@EntityListeners(YourListener.class)添加到實體來注冊實體偵聽器
  2. 將所有@Pre / @Post (例如@PrePersist等)方法的實現添加到YourListener.class ,在那里檢查實體是否是PersistentAttributeInterceptable的實例,如果它只是使用自定義PersistentAttributeInterceptor調用$$_hibernate_setInterceptor返回新的值(特定的行為可能需要經過精心處理以供一般使用,我不確定,但是對於我的簡單測試來說它已經足夠好了 - 你對攔截器的一般用例比我更了解)。

什么是明顯的錯誤的黑客解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM