トランザクションスコープ内でコレクションにアクセスするときに遅延ロードされたコレクションをフェッチする必要があります。たとえば、コレクションを取得したい場合はfoo.getBars.size()
と呼ぶことができます。 ....プロキシ初期化できませんでした -Spring Data JPA - @Transactionalなしでフェッチされたレイジーロードされたコレクション
しかしいいえセッションを:アクティブなトランザクションが存在しない場合は、遅延したバーのコレクションを初期化に失敗しました
のようなエラーメッセージと例外が発生しなければなりません最近のアプリケーションでは動作が違うことに気付きました。私はSpring Boot 1.5.1を "data-jpa"スターターと共に使用しています。私は過去にSpring Bootを使用しましたが、data-jpaスターターは私にとって新しいものです。
以下のケースを考慮してください。私は、怠惰に読み込まれたManyToManyコレクションを持っています。
@SuppressWarnings("serial") @Entity @Table(name = "foo") public class Foo implements java.io.Serializable { .... private Set<Bar> bars = new HashSet<Bar>(0); .... @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinTable(name = "foo_bar_map", joinColumns = {@JoinColumn(name = "foo_id", nullable = false, updatable = false)}, inverseJoinColumns = {@JoinColumn(name = "bar_id", nullable = false, updatable = false)}) public Set<Bar> getBars() { return this.bars; } public void setBar(Set<Bar> bars) { this.bars = bars; }
マイサービスメソッドがトランザクションとしてマークされていないが、私は
@Service public class FooServiceImpl implements FooService { @Autowired private FooRepository fooRepo; @Override public FooDTO findById(int fooId) { Foo foo = fooRepo.findOne(fooId); // The FooDTO constructor will access foo.getBars() return new FooDTO(foo); }
そして、私の期待と過去に
public FooDTO(Foo foo) { ... for (Bar bar : foo.getBars()) { this.bars.add(bar); } }
反しFooDTOコンストラクタのコンテキストのための遅延ロードされたコレクションにアクセスしていますこのコードは正常に実行され、コレクションをフェッチします。さらに、私がサービスメソッドにブレークポイントを投げた場合、コードをステップ実行して、fooRepoを呼び出した後でバーをフェッチするSQLログをログで見ることができます。 fooRepoへの私の呼び出しの後、私はトランザクションが閉じられると予想します。
ここには何が起こっていますか?
サービスを呼び出すのは誰ですか?私の推測では、呼び出し元はトランザクションです。 –
@JBNizetこのメソッドは、トランザクションとしてマークされていないコントローラによって呼び出されます。 –
Springブートは、デフォルトでOpenEntityManagerInViewwInterceptorを使用しているようです:https://github.com/spring-projects/spring-boot/blob//boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java#L203を実行します。 http://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/htmlsingle/#common-application-properties(OpenEntityManagerInViewを検索してください) –