2016-04-12 23 views
0

Bir proje listemiz ve bir müşteri listesi var. Bir proje bir müşteri için olabilir ve her müşterinin çok sayıda projesi olabilir. Bu yüzden projenin sahip olduğu basit bir 1: n ilişki var. esansiyel sadeleştirilmiş Bu bir N + 1 problm nedir ve nasıl düzeltebilirim?

ben projelerin bir listesini yüklediğinizde, aynı anda etkin bir şekilde müşterilere almak isteyen

@Entity 
public class Project { 
    @Id 
    long id; 

    @ManyToOne(optional = true) 
    @JoinColumn(name = "customer", nullable = true, updatable = true) 
    Customer customer; 
} 

@Entity 
public class Customer { 
    @Id 
    long id; 
} 

olduğunu. Durum bu değil. Projeler için tek bir sorgu var ve daha sonra ayrı bir sorguyla karşılaşılan her farklı müşteri için düzenleniyor.

Yani 50 farklı müşteriye atanmış 100 projem var. Bu, projeler için bir sorgu ve müşteriler için 50 sorgu ile sonuçlanacaktır.

Bu, hızlı bir şekilde toplanır ve büyük proje/müşteri listeleri için başvurumuz oldukça yavaşlar. Ayrıca bu sadece bir örnektir. İlişkileri olan tüm varlıklarımız bu davranıştan etkilenir. here önerildiği gibi

Zaten customers sahada @Fetch(FetchMode.JOIN) denedik ama hiçbir şey yapmaz ve FetchMode.SUBQUERY Hazırda için geçerli göre değil:

org.hibernate.AnnotationException: FetchMode.SUBSELECT Kullanımı Toone dernekler izin verilmeyen

Bu sorunu nasıl düzeltebilirim?

+0

Bence bu N + 1 problem için varsayılan getir-tipi sanmıyorum senin 'ManyToOne' ilişkisi zaten' FetchType.EAGER' –

cevap

1

Evet, n + 1'in sorunlu bir kitabının örnek bir örneğidir.

Çoğu durumda kullandığım yaklaşım, ilişkilendirmeyi tembel hale getirmek ve batch size tanımlamaktır.

Alternatif olarak, sorgu sonuç kümesinde doğrudan ilişki başlatmak için [left] join fetch bir JPQL sorgusu kullanabilirsiniz:

select p from Project p left join fetch p.customer 
+0

tek yolu bu mu? Ben soruyorum çünkü Bahar Verilerini kullanıyorum ve her zaman yazılı bir sorgum yok. @Fetch (FetchMode.JOIN) 'aynı şeyi yapmamalı mı? – musiKk

+0

'FetchMode', sorgular üzerinde herhangi bir etkiye sahip değildir (bu nedenle, Spring Data, yine de, depo yöntemlerinde adlandırma kurallarına dayanarak, kaputun altında muhtemelen otomatik olarak oluşturulur). PS Yaylı Verileri, sorgu yazmanızı engellemez. –

+0

Bu doğru, ancak afaik'in sorguları yazmasına izin vermeyen "JpaSpecificationExecutor" arabirimini kullanıyorum. [Getirme modunu bir Spesifikasyonda ayarlayabilirim] (https://jdpgrailsdev.github.io/blog/2014/09/09/spring_data_hibernate_join.html) ama bu bana çok müthiş görünüyor. Temel olarak istediğimi elde etmek için spesifikasyonun bir yan etkisine güvenmek zorundayım. – musiKk

İlgili konular