2011-09-22 12 views
7

私の質問は、JPA 2.0とHibernate、@OneToOneの関係と遅延ロードに関するものです。JPA 2.0/Hibernate: "@OneToOne"でLAZYをフェッチするのはなぜですか?

まず私のセットアップ:

  • 春3.0.5.RELEASE
  • SprnigData JPA 1.0.1.RELEASE
  • にHibernate 3.5.2-決勝
  • DBMS:PostgreSQLの9.0

私は最近、@OneToOneの関係を少なくともバイトコードを持たない怠惰な方法(FetchType.LAZY)で取り出すことはできないという事実を知りました。 n、コンパイル時の織り込みなどを含む。そこに多くのサイトでは、例えば、これを言う:

事は私の設定で、ある、@OneToOneエンティティの遅延ロードが動作しているようです"すぐに使える"と私は本当に理由を理解したいと思っています。 、私のユニットテストを見てください。ただ、「ユーザー」、「avatarImageは」フェッチされないこと、

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

このテストケースは成功し、休止状態SQLのログ出力中に、私ははっきりと見ることができます(1つだけSELECT、無登録しよう、など「AvatarImage」テーブルへのアクセスなし)

は、Userクラスで単方向@OneToOneのrelationshopは次のようになります。

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

、非常に単純なすべてのもの - それはうまくいくようです。

私の質問を繰り返してみてください:それはなぜ動作していますか、なぜ "AvatarImage"は@OneToOne関連で参照されていますが、遅延して取得できますか?

私は本当にあなたが

どうもありがとうを提供することができます任意の助けに感謝します!

答えて

8

OneToOne関係の遅延読み込みの問題は、その逆の部分(mappedBy属性でマークされている部分)のみです。それは関係の所有側でうまく動作します。 T これらの違いは、データベースレベルではっきりしています。あなたの場合、質問は、ユーザデータベーステーブルがAvatarImageのIDを列の1つとして保持しているか、または他の方法で保持しているかどうかです。 ユーザテーブルにIDがAvatarImageのカラムがある場合、遅延ロードは「すぐに使える」と述べたように機能しますが、それ以外の方法では機能しません。

3

バイトコードインストルメンテーションの何らかの形式が実行されたときに、Lazyフェッチは、@OneToOneの注釈付きリレーションシップとHibernate JPAプロバイダとの間でそのまま利用できます。あなたのケースでは、ビルド時の計測を除外することができます(あなたのコメントから、すぐに動作することを推測します)。これにより、ランタイムウィービングの可能性が残されます。これは、HibernateのSpringでかなり可能です。最近のHibernateのリリースでは、CGLIB(which has been deprecated since Hibernate 3.5.5)の代わりに、Hibernateのランタイムバイトコード計測フレームワークとしてJavassistが使用されています。

JavassistがSpringで有効になっているかどうかは、簡単に答えることができます。 Hibernate EntityManager(Hibernate Coreに委譲するJPA 2.0プロバイダ)は、Javassistを必要とするため、Hibernateのクラスパスに存在する必要があり、クラスのランタイムウィービングが可能です。アプリケーションサーバに接続されたリモートデバッガでブレークポイントを設定することでこれを確認できます。UserクラスのHibernate管理インスタンスにはAvatarImageインスタンスへの参照が含まれていません。むしろ、<package_name>.AvatarImage_$$_javassist_0(遅延フェッチを可能にするプロキシです)のような名前を持つ拡張クラスへの参照を含みます。

関連する問題