web-dev-qa-db-ja.com

Hibernateはプロキシを初期化できませんでした-セッションなし

私のコードは、ユーザーに関連するすべての情報を取得します。

_SessionFactory sessionFactory = HibernateUtilities.configureSessionFactory();
Session session = sessionFactory.openSession();
UserDetails ud = null;
Set<Address> userAddress = null;

try {
    session.beginTransaction();
    ud = (UserDetails) session.get(UserDetails.class, 1);
    userAddress = ud.getAddresses();
    session.getTransaction().commit();
} catch (HibernateException e) {
    e.printStackTrace();
    session.getTransaction().rollback();
} finally {
    session.close();
}

System.out.println(ud.getName());

for(Address addr: userAddress){
    System.out.println("State " + addr.getState());
}
_

ud.getAddresses()は、単にユーザーのAddressesのセットを返します。

私の質問は、セッションがすでに閉じられているのに、なぜudオブジェクトにはまだその値(名前など)があるのですか? getAddresses()は、UserDetailsクラスのインスタンス変数です。しかし、なぜその値を取得できないのに、UserDetailsクラスの通常のインスタンス変数を取得できるのでしょうか?

ud.getAddresses()は_@EmbeddedCollection_です。

12
KyelJmD
userAddress = ud.getAddresses();
session.getTransaction().commit();
for(Address addr: userAddress) {

遅延アソシエーションの操作 の休止状態のドキュメントは、この種のアクセスをエラーとして明確に呼び出しています。セッションがまだ開いている間のみ、遅延関連オブジェクトと対話できます。ドキュメントのその部分は、オブジェクトの遅延的に関連付けられたそのようなメンバーにアクセスするための代替手段も提供し、アプリケーションで使用される基準でフェッチモードをJOINとして指定することを好みます。

15
Vikdor

JPA/Hibernateで同じ問題に直面しましたが、この問題を解決するには2つの方法があります。

1 /次のように、デフォルトでLAZYをオフにします。

@Entity
@Proxy(lazy = false)
public class Project {
...
}  

もちろん、パフォーマンスの問題があるため、この方法は推奨されません。したがって、2番目の方法に進むことができます。

2 /メソッドの先頭に@Transactionalを配置できます。セッションを維持するのに役立ちます。または、次のように、セッションの義務をHibernateに渡します。

@Test
@Transactional
public void testSaveGroup() {
    Department g = new Department();
    g.setName("XDG");
    assertNull(g.getId());
    this.groupRepo.save(g);
    assertNotNull(g.getId());
    System.out.println(g.getId());
    Project dummyPrj = new Project(123L, "KSTA", new Date(), "NEW", "Helm AG", g);
    this.projectRepo.save(dummyPrj);
    // verify
    List<Department> lst = this.groupRepo.findAll();
    Project savedPrj = this.projectRepo.getOne(123L);
    Assert.assertEquals("XDG", savedPrj.getGroup().getName());
}

私の答えは遅れていますが、他の誰かを助けたいです:)

19
doannx

クラスのすべてのプリミティブプロパティはすぐにロードされ、バイトコード拡張機能を使用している場合を除き、レイジーになることはできません。コレクションのような実際の関連付けのみが遅延可能です。