2013-06-17 9 views
7

Wystąpiły problemy dzisiaj z leniwym ładowaniem nie działa podczas korzystania z mapowania według kolekcji. Uważam, że to doskonały artykuł, który wydaje się, aby rozwiązać problemLeniwe ładowanie w trybie hibernacji dla odwrócenia jeden do jednego obejścia - jak to działa?

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

Jedno ja nie rozumiem, w jaki sposób obejść stosując FieldHandled działa. Czy ktoś może mi pomóc to zrozumieć? Kod, o którym mowa, znajduje się poniżej (skopiowany z przykładu na łączu):

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

Czego mi brakuje? Być może nie wiem wystarczająco dużo o cyklu życia hibernacji tutaj? Cieszę się, że mogę to zbadać, ale czy ktoś może mi dać jakieś wskazówki.

Z góry dziękuję.

EDIT

I przeforsował wiele zmian tak wielu moich jednostek realizowanych FieldHandled ale potem odkrył niektóre z moich testów niepowodzeniem. Wypompowałem SQL i dostałem kilka dziwnych rzeczy, gdy SQL'y miały miejsce w różnych zamówieniach, jeśli ten interfejs został zaimplementowany przy użyciu tylko tych zestawów metod.

public FieldHandler getFieldHandler() { 
    return fieldHandler; 
    } 

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

To spowodowało, że testy zakończyły się niepowodzeniem, ponieważ sytuacja nie była w prawidłowym stanie, kiedy twierdziłem. To przyczynia się do mojego błędnego zrozumienia tej zmiennej FieldHandler.

Odpowiedz

9

Poniższy kod mówi Hibernate, aby używał procedury przechwytywania zamiast proxy.

@LazyToOne(LazyToOneOption.NO_PROXY) 

From javadoc:

oddać rzeczywisty obiekt ładowany gdy mowa jest o (zwiększenie Bytecode jest wymagana dla tego wariantu, spadek do PEŁNOMOCNIKA gdy klasa nie jest rozszerzony)

Jak widać, przed użyciem należy zaprogramować kod bajtowy. "Klasa upartościowa ulega poprawie" po oprzyrządowaniu jej "kodu bajtowego".

Chodzi o to, aby oszukać Hibernate, że klasa podmiot, który chcemy wykorzystać został już oprzyrządowanej

Instrumentation zadaniem jest wywoływana po kod jest kompilowany. Instrumented entity extends FieldHandled. FieldHandled to "Interfejs wprowadzony do ulepszonej klasy". Weryfikacja obiektów w czasie wykonywania i dochodzenie do wniosku, że klasa została ulepszona, dlatego używa prawdziwego obiektu zamiast proxy i isn't loading related entity object as it normally did.

Edit:

Pozwala spojrzeć pod maską:

  1. AnnotationBinder handlesNO_PROXY opcja

    if (lazy != null) { 
        toOne.setLazy(!(lazy.value() == LazyToOneOption.FALSE)); 
        toOne.setUnwrapProxy((lazy.value() == LazyToOneOption.NO_PROXY)); 
    } 
    
  2. Zarówno org.hibernate.mapping.ManyToOne i org.hibernate.mapping.OneToOne są podklasy org.hibernate.mapping.ToOne. ToOne#isUnwrapProxy() tylko użycie jest w #getType:...

    getMappings() getTypeResolver() getTypeFactory() oneToOne (

  3. Zarówno ManyToOneType i OneToOneType są podklasy EntityType i tylko użycie 'EntityType # unwrapProxy' jest EntityType#resolveIdentifier(Serializable, SessionImplementor)

    boolean isProxyUnwrapEnabled = unwrapProxy && 
         session.getFactory() 
           .getEntityPersister(getAssociatedEntityName()) 
           .isInstrumented(); 
    
  4. Oto Wstępna hierarchia wezwanie: AbstractEntityPersister#isInstrumented() ->EntityMetamodel#isInstrumented() ->EntityInstrumentationMetadata#isInstrumented() -> itd. i wreszcie BytecodeProviderImpl.EntityInstrumentationMetadataImpl.EntityInstrumentationMetadataImpl()

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

Dlatego nie jest to wymagane albo przyrząd kod (np z InstrumentTask) lub wdrożenie FieldHandled.


W celu uzyskania krótkiego opisu można zapoznać się z EntityType#resolveIdentifier(Serializable, SessionImplementor). That's the reason why second object is not loaded even if it's nullable.

+0

Dzięki @lifus To wygląda to posiada wszystkie informacje potrzebne hte . Przejdę przez to. Z tego, co widziałem, mówisz, choć nadal nie jestem pewien, dlaczego otrzymuję SQL uruchamiane w innej kolejności. Być może będę musiał zbadać to jeszcze ... – RNJ

+0

próbując przyznać ci nagrodę, ale jestem na urządzeniu mobilnym. jeśli nie mogę tego rozgryźć, powinieneś pobrać go automatycznie, gdy wkrótce wygasa. Dziękuję za odpowiedź – RNJ

4

Interfejs FieldHandled został zastąpiony interfejsem PersistentAttributeInterceptable w Hibernate 5. Można osiągnąć ten sam rezultat poprzez wdrożenie tego nowego interfejsu:

@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; 
    } 
} 
Powiązane problemy