2017-03-03 34 views
6

Beklentim, koleksiyona bir işlem kapsamı içinde erişildiğinde tembel yüklenmiş bir koleksiyonun getirilmesi gerektiğidir. Örneğin, bir koleksiyon almak istersem, foo.getBars.size()'u arayabilirim. .... vekil başlatılamadı olabilir -Spring Data JPA - Lazy Loaded collection @Transactional olmadan getirildi

Ancak hiçbir Oturumu: Aktif bir işlemin olmaması tembel barlar bir koleksiyon başlatılamadı

gibi bir hata mesajı ile bir özel duruma neden olacaktır En son uygulamamda davranışın farklı olduğunu fark ettim. Spring Boot 1.5.1'i "data-jpa" marş motoru ile kullanıyorum. Geçmişte Spring Boot kullanmıştım, ancak data-jpa starter benim için yeni. Aşağıdaki durumu göz önünde bulundurun. Tembel yüklü ManyToMany koleksiyonum var.

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

hizmetim yöntemi işlemsel olarak işaretlenmiş DEĞİLDİR ama

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

Ve beklenti ve geçmişe

public FooDTO(Foo foo) { 
    ... 
    for (Bar bar : foo.getBars()) { 
     this.bars.add(bar); 
    } 
} 

aksine FooDTO yapıcı bağlam için tembel yüklenen koleksiyonu erişiyorum deneyim, bu kod başarıyla yürütür ve koleksiyon getirir. Ayrıca, hizmet yöntemimde bir kesme noktası atarsam, kodun içinden geçebilir ve fooRepo’ya aramamın ardından çubukları getiren günlüklerimdeki SQL deyimlerini görebilirim. FooRepo'yu aradıktan sonra, işlemin kapatılmasını bekliyorum.

Burada neler oluyor?

+0

Servisi kim arıyor? Tahminim, arayanın işlemsel olması. –

+0

@JBNizet Yöntem, işlemsel olarak işaretlenmemiş bir denetleyici tarafından çağrılır .... –

+1

Yay önyükleme, varsayılan olarak bir OpenEntityManagerInViewwInterceptor kullanıyor: https://github.com/spring-projects/spring-boot/blob/ ana/yay çizme-autoconfigure/src/main/java/org/spring Framework/boot/autoconfigure/orm/JPA/JpaBaseConfiguration.java # L203. Ayrıca bkz. Http://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/htmlsingle/#common-application-properties (ve OpenEntityManagerInView için arama) –

cevap

11

Spring Boot, varsayılan olarak bir OpenEntityManagerInView engelleyicisi kullanır. spring.jpa.open-in-view özelliğini false olarak ayarlayarak kapatabilirsiniz.

Bu (ve diğer) JPA özellikleriyle ilgili referans için bkz the documentation.

+0

dışarıda yani findById, artık çalışmayacak mı? –

1

Bir İşlemin açılıp açılmadığını kontrol etmek için günlüğe kaydetmeyi açabilirsiniz.

org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction 

veya

org.hibernate.engine.transaction.internal.jta.JtaTransaction 

Ayrıca, bir kesme noktası ayarlamak ve bir hareketin açık olup olmadığını kontrol etmek bu statik yöntemi kullanabilirsiniz.

org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive() 
İlgili konular