2011-09-22 9 views
7

moje pytanie dotyczy JPA 2.0 ze związkami Hibernate, @OneToOne i leniwym ładowaniem.JPA 2.0/Hibernate: Dlaczego LAZY pobiera z "@OneToOne" działa po wyjęciu z pudełka?

Pierwsza moja konfiguracja:

  • Wiosna 3.0.5.RELEASE
  • SprnigData JPA 1.0.1.RELEASE
  • Hibernate 3.5.2-final
  • DBMS: PostgreSQL 9.0

Niedawno natknąłem się na fakt, że relacji @OneToOne nie można pobrać leniwy sposób (FetchType.LAZY), przynajmniej nie bez kodu bajtowego instrumentatio n, kompiluj tkanie czasu lub tym podobne. Wiele witryn, powiedzieć to, na przykład:

Chodzi o to, z mojej konfiguracji, lazy loading podmiotu @OneToOne wydaje się działać "po wyjęciu z pudełka" i naprawdę chciałbym zrozumieć dlaczego. Proszę spojrzeć na moje testów jednostkowych:

@Test 
@Transactional 
public void testAvatarImageLazyFetching() 
{ 
    User user = new User(); 
    user.setAvatarImage(new AvatarImage()); 

    User = userRepository.save(user); 

    entityManager.flush(); 
    entityManager.clear(); 

    User loadedUser = userRepository.findOne(user.getId()); 
    assertNotNull(loadedUser); 

    PersistenceUtil persistenceUtil = Persistence.getPersistenceUtil(); 

    assertTrue(persistenceUtil.isLoaded(loadedUser)); 
    assertFalse(persistenceUtil.isLoaded(loadedUser, "avatarImage")); 
} 

Sprawa ta próba się powiedzie, w Hibernacja wyjścia logowania SQL, widzę wyraźnie, że „avatarImage” nie będą pobierane, tylko „użytkownik” (tylko jeden SELECT, nie JOIN, nie ma dostępu do „AvatarImage” stół itd)

jednokierunkowy @OneToOne relationshop w klasie użytkownika wygląda następująco:

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
private AvatarImage avatarImage; 

Tak, wszystko bardzo proste - i wydaje się działać.

Aby powtórzyć moje pytanie: dlaczego to działa, dlaczego "AvatarImage" może być leniwie ściągany, mimo że jest powiązany ze stowarzyszeniem @OneToOne?

naprawdę wdzięczni za każdą pomoc można zaoferować

Dzięki wielkie!

Odpowiedz

8

Problem z leniwym ładowaniem relacji OneToOne występuje tylko w jego odwrotnej części (ta, która jest oznaczona atrybutem mapowanyBy). Działa dobrze na własnej stronie związku. T Różnica między tymi wartościami jest wyraźna na poziomie bazy danych. W twoim przypadku pytanie brzmi, czy tabela bazy danych użytkownika zawiera identyfikator AvatarImage jako jednej z kolumn lub odwrotnie. Jeśli tabela użytkownika ma kolumnę z identyfikatorem AvatarImage, to leniwy ładunek będzie działał tak, jak powiedziałeś "out-of-box", ale nie będzie działać na odwrót.

3

Lazy fetching działa po wyjęciu z pudełka dla @OneToOne relacji z adnotacjami, z dostawcą Hibernate JPA, gdy wykonywana jest jakaś forma instrumentacji kodu bajtowego. W twoim przypadku moglibyśmy wykluczyć oprzyrządowanie w czasie budowania (wywnioskowanie z twojego komentarza, że ​​działa po wyjęciu z pudełka). Pozostawia to możliwość tkania w czasie wykonywania, co jest całkiem możliwe w Hibernate & Spring. W ostatnich wydaniach Hibernate, Javassist jest używany jako framework oprzyrządowania bytecode dla Hibernate, w przeciwieństwie do innej alternatywy CGLIB (which has been deprecated since Hibernate 3.5.5).

Pytanie, czy Javassist jest włączony na wiosnę, jest dość proste. Hibernuj EntityManager (który jest dostawcą JPA 2.0, który deleguje do Hibernate Core), wymaga Javassist, a zatem powinien znajdować się w ścieżce klasy Hibernate, umożliwiając tkanie klas w czasie wykonywania.Możesz to potwierdzić, ustawiając punkt przerwania (w zdalnym debugerze podłączonym do serwera aplikacji), a zauważysz, że wystąpienie zarządzane przez hibernację klasy User nie będzie zawierało odwołania do instancji AvatarImage; raczej zawierałoby odniesienie do ulepszonej klasy o nazwie takiej jak <package_name>.AvatarImage_$$_javassist_0 (która jest proxy, która pozwala na leniwe pobieranie).

Powiązane problemy