0

とマークされたサービスがあります@Transactional。唯一の問題は、save メソッドを呼び出すときにオブジェクトをコミットする必要があるメソッドに取り組んでいることです。

クラス レベルから注釈を削除し、私のものを除く各メソッドを@Transactional(DAO も とマークされています@Transactional) としてマークしました。情報が希望どおりにすぐに保存されていることがわかりますが、findBy を実行しようとすると、「スレッド内にセッションが存在しません」という例外が発生します。

この問題とその修正方法を知っている人はいますか?

4

1 に答える 1

2

そのため、サービス クラスと DAO が何を行っているかについての詳細が提供されていないため、メソッドが何を行っているかについて、いくつかの経験に基づいた推測を行う必要があります。

サービス@Transactionalクラスはトランザクション セッションを管理する必要があるためです。DAO は、データベースにアクセスし、オブジェクトをフォームで返して使用できるようにするためにのみ使用する必要があります。セッションは、DAO が気にする必要があるものではありません。

ここで、サービス クラスは次のようになると推測します。

@Transactional
public void saveOrUpdateFoo(Foo foo){
    fooDao.saveOrUpdate(foo);
}

@Transactional
public Foo manipulateFoo(Foo foo){
    //Do stuff to your Foo object that you want to be changed.
    saveOrUpdateFoo(foo);
    //Database hasn't actually changed yet.
    foo = fooDao.findBy(foo.getFooId());
    //nothing will change here.
}

を呼び出したときにデータベースが実際に変更されない理由を理解するには、アノテーションが実際に Hibernate にも影響を与える原因saveOrUpdateFoo(foo)を理解する必要があります。@Transactionalメソッドをマークすると@Transactional、このメソッド内のすべてが単一のデータベース セッションで発生する必要があり、問題が発生した場合はロールバックする必要があることを Hibernate に伝えます。

これを容易にするためcurrentSession().save(foo);に、DAO を呼び出すと (そうしていると思います)、Hibernate はオブジェクトを取得し、メモリ内のそのオブジェクトのローカル 'クローン' を更新します。(これは実際の動作ではありませんが、Hibernate がトランザクションの開始時にデータベースに基づいてオブジェクトの独自のコピーを保持していると想像してください。save/update を呼び出すと、これらのコピーが変更されます)

メソッドが終了する@Transactionalと、Hibernate はこれらの変更をデータベースにフラッシュします。これは、データベースの状態が実際に変化するときです。このオブジェクトが新しいオブジェクトである場合 (データベースで新しいレコードを作成する必要がある場合など)、Hibernate はsaveOrUpdateFoo、データベースの保存時に使用される値で呼び出したときに管理する ID フィールドを更新する必要があります。オブジェクトを保存したら、オブジェクトを「再取得」する必要はありません。実際にINSERTデータベースに「取得」したかのようSELECTに、変更が実際に永続化されることなく、再度「取得」する必要があります。データベース。

これは、すべての処理中に別のスレッドでデータベースからオブジェクトを取得しようとしている場合を除き、問題にはなりません。その場合は、サービス クラスを再設計して、それが起こらないようにする必要があります。

これで問題が解決しない場合は、実際に何をしようとしているかの説明とともに、サービス クラスと DAO を投稿してください。

于 2015-03-24T05:16:52.543 に答える