作業中のアプリを AspectJ ロード時間織りの使用から Spring CGlib プロキシの使用に切り替えました。その直後にコードの多くの部分で休止状態の遅延読み込み例外が発生し始めましたが、過去には例外はありませんでした。投げた。
これらの遅延読み込みの例外@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
は、トランザクション属性を持たず、データベースからデータを読み取るためのスプリング リポジトリと呼ばれる、以前は公開されていた一連のメソッドを追加することで解決できました。
追加@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
すると休止状態の遅延読み込みの例外がなくなる理由と、これらの注釈が AspectJ の読み込み時間の織り方では必要ないのに、out なしでは必要な理由を知っている人はいますか?
更新 2 AspectJ を削除することは問題ではないと思いますが、問題は、SUPPORTS 伝播の実際の動作をよく理解していなかったことです。特に、SUPPORTS が JPA EntityManager とどのようにやり取りしたかということで、遅延読み込み例外の原因となった SUPPORTS 伝播の束を削除しました。Spring Transaction Manager のソース コードを読んだ後、何をすべきかがすべて明確になりました。Spring のドキュメントがあまりよく指摘していない重要なアイデアは、@Transactional アノテーションが、EntityManager のライフサイクルをトランザクション メソッドの開始と終了に結び付ける同期ポイントとして使用されるということです。また、この一連の記事 ( http://www.ibm.com/developerworks/java/library/j-ts1/ ) およびこのブログ記事も強くお勧めします。http://doanduyhai.wordpress.com/2011/11/21/spring-persistencecontext-explained/
更新 1
これは、AOP プロキシを経由しないプライベート @Transactional メソッドへの呼び出しの場合ではありません。これらの問題は、他のサービスから呼び出されているパブリック メソッドで発生しています。
問題が発生しているコード構造の例を次に示します。
@Service
public class FooService
{
@Autowired
private BarService barService;
public void someMethodThatOnlyReads() {
SomeResult result = this.barService.anotherMethodThatOnlyReads()
// the following line blows up with a HibernateLazyLoadingEcxeption
// unless there is a @Transactional supports annotation on this method
result.getEntity().followSomeRelationship();
}
}
@Service
public class BarService
{
@Autowired
private BarRepository barRepo;
public SomeResult anotherMethodThatOnlyReads()
{
SomeEntity entity = this.barRepo.findSomeEntity(1123);
SomeResult result = new SomeResult();
result.setEntity(entity);
return result;
}
}
@Repository
public class BarRepository
{
@PersistenceContext
private EntityManager em;
public SomeEntity findSomeEntity(id Integer)
{
em.find(SomeEntity.class,id);
}
}