簡體   English   中英

Hibernate延遲加載反向一對一解決方法 - 這是如何工作的?

[英]Hibernate lazy loading for reverse one to one workaround - how does this work?

今天我遇到問題,延遲加載在使用映射集合時無法正常工作。 我發現這篇優秀的文章似乎解決了這個問題

http://justonjava.blogspot.co.uk/2010/09/lazy-one-to-one-and-one-to-many.html

我不明白的一件事是使用FieldHandled的解決方法是如何工作的。 任何人都可以幫我理解這個嗎? 有問題的代碼如下(從鏈接上的示例中復制):

@Entity
public class Animal implements FieldHandled {
   private Person owner;
   private FieldHandler fieldHandler;

   @OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal")
   @LazyToOne(LazyToOneOption.NO_PROXY)
   public Person getOwner() {
     if (fieldHandler != null) {
        return (Person) fieldHandler.readObject(this, "owner", owner);
     }
     return owner;
   }

   public void setOwner(Person owner) {
     if (fieldHandler != null) {
       this.owner = fieldHandler.writeObject(this, "owner", this.owner, owner);
       return;
     }
     this.owner = owner;
   }

   public FieldHandler getFieldHandler() {
     return fieldHandler;
   }

   public void setFieldHandler(FieldHandler fieldHandler) {
     this.fieldHandler = fieldHandler;
   }
}

我錯過了什么? 也許我對hibernate的生命周期知之甚少? 我很高興調查,但任何人都可以給我一些指示。

提前致謝。

編輯

我推動了很多變化,所以我的很多實體都實現了FieldHandled但后來發現我的一些測試失敗了。 我抽出了SQL並得到了一些奇怪的東西,如果這個接口是用這些方法集實現的,那么SQL會以不同的順序發生。

   public FieldHandler getFieldHandler() {
     return fieldHandler;
   }

   public void setFieldHandler(FieldHandler fieldHandler) {
     this.fieldHandler = fieldHandler;
   }

這導致測試失敗,因為當我斷言時,事情並沒有完全處於正確的狀態。 這增加了我對這個FieldHandler變量的誤解。

以下代碼告訴Hibernate使用攔截處理程序而不是代理。

@LazyToOne(LazyToOneOption.NO_PROXY)

來自javadoc:

在請求引用時返回加載的實際對象(此選項必須使用字節碼增強,如果未增強類,則返回PROXY)

可以看出,在使用之前需要檢測字節碼。 在''字節碼被檢測'后,'持久類被增強'。

我們的想法是欺騙Hibernate我們想要使用的實體類已經被檢測過了

編譯代碼后調用Instrumentation任務。 檢測實體擴展了FieldHandled FieldHandled是一個'引入增強類的接口'

Hibernate在運行時驗證實體,並得出結論,類已被增強,這就是為什么它使用真實對象而不是代理, 並且不像通常那樣加載相關的實體對象

編輯:

讓我們來看看引擎蓋:

  1. AnnotationBinder處理 NO_PROXY選項

     if ( lazy != null ) { toOne.setLazy( !( lazy.value() == LazyToOneOption.FALSE ) ); toOne.setUnwrapProxy( ( lazy.value() == LazyToOneOption.NO_PROXY ) ); } 
  2. 無論org.hibernate.mapping.ManyToOneorg.hibernate.mapping.OneToOne是子類org.hibernate.mapping.ToOne ToOne#isUnwrapProxy()僅用於#getType

    getMappings()。getTypeResolver()。getTypeFactory()。oneToOne(

  3. ManyToOneTypeOneToOneType都是EntityType子類,只有'EntityType#unwrapProxy'的使用在EntityType#resolveIdentifier(Serializable, SessionImplementor)

     boolean isProxyUnwrapEnabled = unwrapProxy && session.getFactory() .getEntityPersister( getAssociatedEntityName() ) .isInstrumented(); 
  4. 這是暫定的調用層次結構: AbstractEntityPersister#isInstrumented() - > EntityMetamodel#isInstrumented() - > EntityInstrumentationMetadata#isInstrumented() - >等等,最后是BytecodeProviderImpl.EntityInstrumentationMetadataImpl.EntityInstrumentationMetadataImpl()

      this.isInstrumented = FieldHandled.class.isAssignableFrom( entityClass ); 

這就是為什么需要檢測代碼(例如使用InstrumentTask )或實現FieldHandled


為了簡而言之,您可以查看EntityType#resolveIdentifier(Serializable, SessionImplementor) 這就是為什么第二個對象即使可以為空也不會被加載的原因。

FieldHandled接口已被Hibernate 5中的PersistentAttributeInterceptable接口替換。您可以通過實現此新接口來實現相同的結果:

@Entity
public class Animal implements PersistentAttributeInterceptable {
    private Person owner;
    private PersistentAttributeInterceptor interceptor;

    @OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal")
    @LazyToOne(LazyToOneOption.NO_PROXY)
    public Person getOwner() {
        if (interceptor != null) {
            return (Person) interceptor.readObject(this, "owner", owner);
        }
        return owner;
    }

    public void setOwner(Person owner) {
        if (interceptor != null) {
            this.owner = interceptor.writeObject(this, "owner", this.owner, owner);
            return;
        }
        this.owner = owner;
    }

    @Override
    public PersistentAttributeInterceptor $$_hibernate_getInterceptor() {
        return interceptor;
    }

    @Override
    public void $$_hibernate_setInterceptor(PersistentAttributeInterceptor interceptor) {
        this.interceptor = interceptor;
    }
}

暫無
暫無

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

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