2010-10-22 22 views
10

Benim Wicket + JPA/Hazırda Bekletme + Bahar projemde, pek çok filtreleme seçeneği (tümü kullanılmamalıdır) kullanan kullanıcılar, kümeyi kısıtlayabilir. Çalışmak istedikleri nesnelerin Bu filtreyi uygulamak için en iyi stratejinin ne olduğunu merak ediyordum? Bu uygulamanın eski sürümünde, arama sorgusu SQL koşullarını içeren dizeleri birleştirdi. Kısa bir süre önce yeni Ölçüt API'sı JPA ile ilgili bilgiler okudum - bu arama dizgisiyle çalışmayı önerir misiniz? Bu, DAO katmanıyla nasıl birleştirilir? - iş katmanında Kriteri API'sı kullanılarak arama sorgusu oluşturulmuyor, katmanların ayrılmasında bir ihlal var mı?Karmaşık Arama Sorguları JPA

cevap

4

Anlattığınız gibi sorguları filtrelemek için Koşullu sorgular için destek nedeniyle Hibernate veya JPA ölçüt API'sini kullanmanızı kesinlikle öneririz. Genelde sadece inşaat kurallarını DAO'larma koyarım ve oradaki tüm gerekli (muhtemelen null) argümanları iletirim.

İşte hazırda kriterleri API kullanarak bir örnek araba kiralama uygulamadan bir örnek DAO yöntemi var:

Bir SQL katılmak gerekir nerede createAlias ​​çağrı kullanılabilir
public List<VehicleRentalContract> list(Long contractID, 
      String customerNameOrID, Date date, 
      String vehicleDescriptionOrRegistration) { 
     Criteria criteria = getSession().createCriteria(
       VehicleRentalContract.class); 
     // contractID filter 
     if (contractID != null && contractID != 0) { 
      criteria.add(Restrictions.eq("id", contractID)); 
     } 
     // customerNameOrID filter 
     if (customerNameOrID != null && customerNameOrID.length() > 0) { 
      try { 
       Long customerID = Long.parseLong(customerNameOrID); 
       criteria.add(Restrictions.eq("customer.id", customerID)); 
      } catch (NumberFormatException e) { 
       // assume we have a customer name 
       String customerNameQuery = "%" + customerNameOrID.trim() + "%"; 
       criteria.createAlias("customer", "customer").add(
         Restrictions.or(Restrictions.like("customer.firstName", 
           customerNameQuery), Restrictions.like(
           "customer.lastName", customerNameQuery))); 
      } 
     } 
     // date filter 
     if (date != null) { 
      criteria.add(Restrictions.and(
        Restrictions.le("rentalPeriod.startDate", date), 
        Restrictions.ge("rentalPeriod.endDate", date))); 
     } 

     // vehicleDescriptionOrRegistration filter 
     if (vehicleDescriptionOrRegistration != null 
       && vehicleDescriptionOrRegistration.length() > 0) { 
      String registrationQuery = "%" 
        + Vehicle 
          .normalizeRegistration(vehicleDescriptionOrRegistration) 
        + "%"; 
      String descriptionQuery = "%" 
        + vehicleDescriptionOrRegistration.trim() + "%"; 

      criteria.createAlias("vehicle", "vehicle").add(
        Restrictions.or(Restrictions.like("vehicle.registration", 
          registrationQuery), Restrictions.like(
          "vehicle.description", descriptionQuery))); 
     } 

     List<VehicleRentalContract> contracts = criteria.list(); 
     return contracts; 
} 

.

+0

+1. Birisi, customerNameOrID parametresinin kullanımı hakkında tartışabilirdi. Aksi halde "ve" ile ilgili parametrelere bir "veya" yerleştirmek gibi görünüyor. Veri türleri eşit olduğunda bir durum söz konusu olduğunda bu durum rasgele karmaşıklaşabilir. Bu durumlar için muhtemelen farklı parametre setleriyle aşırı yüklenmeler oluşturmak en iyisidir. –

+0

@Adriaan Koster Argüman listeniz, aramanızı çizen bir sınıf tarafından değiştirilebilir; örneğin, ** VehicleRentalContractCriteria ** –

+0

@Martin 'customerNameOrID', kullanıcının müşterinin bir bölümünü girebileceği bir metin giriş alanından gelir. ad veya müşteri kimliği. İç içe YA'yı basitleştirmeyi nasıl önerdiğinizi tam olarak göremiyorum, lütfen bize göster. –

1

bile HQL ve SQL üzerinden Kriterler kullanmayı tercih ediyorum, çünkü benim için modülerlik ve performans da geçerli olacak çünkü proje üretime başladığında karşılaştığımız en büyük sorun performans değil, ne HQL ne de SQL de Kriterler üzerinde rekabet edemez performans.

Yukarıda ekleme DAO katmanı, verilere erişmek için oluşturulmuştur ve bu katman, karmaşık kodlama veya iş mantığı olmadan, cam kadar net olmalıdır, ancak ölçütler söz konusu olduğunda, bir mantık yazmalıdır (ölçütler oluşturun). nesneye erişmek için daha iyi ve ayarlı bir şekilde varmak için, Bu yüzden benim görüşüme göre DAO katmanında bu kadar mantığı koymada herhangi bir ihlal yoktur.

+0

Herhangi bir üst düzey API'nin SQL'den daha iyi performans gösterebileceğini sanmıyorum çünkü her şeyden sonra SQL sorgusu olarak ortaya çıkıyor. –

1

iki yaklaşım:

1 .. bağlı filtreleme ne tür üzerinde size örneğin arayarak bu modernleşmek mümkün olabilir gerek Lucene ile tüm nesneleri indeksleyin ve filtrelemeyi yapmak için arama sorgularını kullanın.

başlığı: "Doğru" & mod_date: örneğin, bir sorgu gibi inşa [20020101 20030101 İÇİN]

Bkz: http://lucene.apache.org/java/2_4_0/queryparsersyntax.html


2 .. Ya ölçütleri kullanarak ...

http://relation.to/12805.lace

:

Ben hazırda yeni tip-güvenli kriterler API kullanmak istiyorum inşa etmek mümkün olacaktır, bu ikisinin bir kombinasyonuyla

http://docs.jboss.org/hibernate/core/3.5/reference/en/html/querycriteria.html#querycriteria-detachedqueries

- çok büyük kriterlerini kurar

yerine bir yöntem, ben müstakil kriterler kullanılarak tüm mantığı dışarı ayırmak için çalışacaktı kriterleri kolayca. İlham bulmak için başka bir yer de dinleyicilerin dinamik bulucularıdır. Bu aslında statik bir şekilde başarmaya çalıştığınız şeydir.

http://www.grails.org/doc/1.0.x/guide/single.html#5.4.1 Dinamik Bulucular

Gerçekten basit dilbilgisi uygulamak tabakaların tamamen ayrılmasını istiyorum. Sonra ilgili kriterleri oluşturmak için bunu ayrıştırın. Bu, altta yatan kriter uygulamalarının değiştirilmesine izin verecektir. Bunun uygun olup olmadığı, bu soyutlamanın sizin için ne kadar önemli olduğuna bağlıdır. Temel kavram için