2012-10-09 14 views
6

Bağlantı tablosunda ek bir sütunla çoktan çoğa ilişkisi var. Bunu, sahip olmanın çocukları hevesli bir şekilde (LazyInitializationException almıyorum) ve ters yönde tembel olduğu şekilde yapılandırdım. Bu çalışıyor. .@Transactional (readOnly = true), LazyInitializationException öğesine yol açar.

@Transactional(readOnly = true) 
public Compound getById(Long id) { 
    return compoundDAO.getById(id); 
} 

Bu değişiklikten sonra bir LazyInitializationException olsun:

Ben şimdi readOnly = true yöntemi getById set sadece @Transactional DAO ve Servis sınıfların sınıf düzeyinde oldu önce (işlemler ince ayar istedi aşağıdaki pasajı:

Compound compound = compoundService.getById(6L);   
Structure structure = compound.getComposition().get(0).getStructure(); 
System.out.println("StructureId: "+ structure.getId()); // LazyInitializationException 

herkes bu davranış açıklayabilir bu işleri (readOnly = true) kaldırırsanız neden inci bir neden görmüyorum ben kafa karıştırıcı Bahar + Hibernate Kind kullanın!?. hangi verinin yüklendiğini etkilemeli?


DÜZENLEME: ilişki tanımlarının

Parçacıklar. Bu, bağlantı tablosundaki bir sütuna çoktan çoğa var.

sahip olmak tarafı (örneğin, uygun bileşik içerir):

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.structure", 
cascade = CascadeType.ALL) 
@OrderBy("pk.compound.id ASC") 
private List<CompoundComposition> occurence; 

Çok-one @Embeddable İD sınıfı

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
public Compound getCompound() { 
    return compound; 
} 

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
public Structure getStructure() { 
    return structure; 
} 

DÜZENLEME 2:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.compound", 
    cascade = CascadeType.ALL, orphanRemoval = true) 
@OrderBy("pk.structure.id ASC") 
private List<CompoundComposition> composition = new ArrayList<>(); 

yan Ait :

St ack İz

org.hibernate.LazyInitializationException: could not initialize proxy - no Session 
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final] 
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:272) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final] 
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) ~[hibernate-core-4.1.7.Final.jar:4.1.7.Final] 
    at org.bitbucket.myName.myApp.entity.Structure_$$_javassist_0.getId(Structure_$$_javassist_0.java) ~[classes/:na] 
    at org.bitbucket.myName.myApp.App.main(App.java:31) ~[classes/:na] 

DÜZENLEME 3:

Giriş Readonly ile çok farklı ve parça ilişkiler örneğin yüklenen vardı eksik:

Ayrıca benim yorumu görmek. Bazı seçmeler günlüğünde eksik.

DÜZENLEME 4: Temel bir DriverManagerDataSource ve hiçbir bağlantı havuzlu

yüzden yorgun. Sorun tam olarak aynı. Benim için Hibernate bir sorun gibi görünüyor. geç yükleme işlemi içinde olur, böylece

+0

Sınıf düzeyi işlem tanımı nedir? –

+0

Sadece @ Transactional. –

+0

Model sınıflarının snippet'lerini yayınlayabilir misiniz? Ve hala, DAO sınıfının en üstünde 'Transactional 'açıklaması var mı? – sbzoom

cevap

3

Bu sadece bir vay. Bazı insanların ORM'lerden neden nefret ettiğini anlamaya başladım ... Sadece garip bir sorunu çözmek için saatlerimi harcamak zorunda olduğumu hissettim ve çözüm çok özel bir açıklama dizisidir + söz konusu sınırların etrafında çalışmak için bazı kodlar ek açıklamalar.

İlk olarak, bunun neden gerçekleştiği (mantıksal anlamda mantıklı bir anlam ifade etmese de, anlamsızlık anlamında anlamsız olan anlamsızdır.) Sadece deneme ve hata yardımcı olur. Sahip olmak için, @OneToMany'de yetimizim = doğru (ki bunun tutarlılık için gerekli olduğunu öğrendim. Biri veritabanı kısıtlamalarının ele alması gerektiğini düşünürdü ... bu sizi delirtebilecek birçok şeyden sadece biri.). salt okunur bir işlemde

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
public Structure getStructure() { 
    return structure; 
} 

, bu alımlı olmaz: işlem salt okunur değilse, o zaman bu ayar bazı veriler bile yani burada, onun tembel böylece alınıyor yol açtığı görülmektedir. Tahmin edersem, çünkü hiçbir şeyi değiştiremezseniz, yetimlerin kaldırılması gerekmeyecek ve dolayısıyla bu ayarın arkasındaki mantığın salt okunur bir tx'de gerekmediği herhangi bir veriye gerek kalmayacaktır. Böylece, açık çözüm FetchType.EAGER ile değiştirilmek için yukarıdaki ilişkide olacaktır. Yanlış! Bunu yaparsanız, session.merge kullanarak sahip olduğunuz tarafı (Bileşen) güncelleyemezsiniz. Bu StackOverFlowError için yol açacaktır. Gerçek çözüm aslında daha önce bahsedilmiştir. olduğu gibi sadece yapılandırma bırakın ancak açıkça Servis tabakada istenen ilişkileri yüklemek:

@Transactional(readOnly = true) 
@Override  
public Compound getById(Long id) { 

    Compound compound = compoundDAO.getById(id); 
    for (CompoundComposition composition : compound.getComposition()){ 
     Hibernate.initialize(composition.getStructure()); 
    }   
    return compound; 
} 

Ben erken optimizasyon tuzağa düşmek eğiliminde değilim itiraf. Bu çok verimli görünmüyor ve SQL'in ilk olarak nasıl çalıştığını da gösteriyor. Ama sonra çoğu durumda CompoundComposition sadece 1 veya 2 elementleri içerecek şanslı pozisyondayım.

+1

İlk iki paragrafınız, Hibernate/JPA/ORM'lerle geçirdiğim 6-ya da yıllarını özetliyor. – millhouse

0

Belki, getById() yöntemin gövdesinde

value.getComposition().get(i).getStructure(); 

koyabilirim. Bu durumda, uygunsuz olabilecek i'u aşmanız gerektiğini anlıyorum.

İlgili konular