2011-01-25 13 views
6

DB2 ve MySQL'e karşı hibernate kullanarak aynı sorunu yaşıyorum.JPA2 critera sorgudaki FK sorunları n ifadesi ifadeleri, burada n # değer var

 EntityManager em = emf.createEntityManager(); 
     CriteriaBuilder cb = em.getCriteriaBuilder(); 
     CriteriaQuery<Customers> query = cb.createQuery(Customers.class); 
     Root<Customers> root = query.from(Customers.class); 

     ArrayList<String> strList = new ArrayList<String>(); 
     strList.add("ADMIN"); 
     strList.add("SYSADMIN"); 
     strList.add("SALES"); 

     ArrayList<Predicate> predicateList = new ArrayList<Predicate>(); 

     Path<Groups> groups = root.get(Customers_.groups); 
     Path<String> groupName = groups.get(Groups_.name); 
     In<String> in = cb.in(groupName); 
     for (String s : strList) { //has a value 
      in = in.value(s); 
     } 
     predicateList.add(in); 
     Predicate[] predicates = new Predicate[predicateList.size()]; 

     query.where(predicateList.toArray(predicates)); 
     TypedQuery<Customers> typedQuery = em.createQuery(query); 
     this.outList = typedQuery.getResultList(); 

Üç gereksiz sorguları ardından gerek sorgu (birçok değerler strList olduğu gibi için ek bir) üretir: Burada

bir testtir. Aşağıdakiler günlükte yazdırılır (ilk sorguyu ayırmak için oluşturdum.) İlk sorgu, tam olarak istediğim şeyi yapar; bu, üretimde istisna aldığım gereksiz IO'ya neden olan sonraki üç sorundur. Not ifadesindeki , FK'de değilse, bu sorun oluşmaz.

INFO: Hibernate: 
select 
    customers0_.id as id0_, customers0_.fname as fname0_, customers0_.groups as groups0_, customers0_.lname as lname0_ 
from 
    test.customers customers0_ 
where 
    customers0_.groups in (? , ? , ?) 

INFO: Hibernate: select groups0_.name as name1_0_ from test.groups groups0_ where groups0_.name=? 
INFO: Hibernate: select groups0_.name as name1_0_ from test.groups groups0_ where groups0_.name=? 
INFO: Hibernate: select groups0_.name as name1_0_ from test.groups groups0_ where groups0_.name=? 

Neden fazladan üç sorgular? Onları nasıl önleyebilirim? Cevabı bir Ölçüt Sorgusu olarak istiyorum. İşte


varlık nesneleri şunlardır:

@Entity 
@Table(name = "customers", catalog = "test", schema = "") 
public class Customers implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id", nullable = false) 
    private Integer id; 
    @Column(name = "fname", length = 45) 
    private String fname; 
    @Column(name = "lname", length = 45) 
    private String lname; 
    @JoinColumn(name = "groups", referencedColumnName = "name") 
    @ManyToOne 
    private Groups groups; 

...getters and setters... 
} 

Sonraki varlık

@Entity 
@Table(name = "groups", catalog = "test", schema = "") 
public class Groups implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @Basic(optional = false) 
    @Column(name = "name", nullable = false, length = 45, unique = true) 
    private String name; 
    @OneToMany(mappedBy = "groups") 
    private Collection<Customers> customersCollection; 

...getters and setters... 
} 

Düzenleme ~~~~~~~~~~~~~~~~~ ~~~~~~~~ ÇÖZÜM ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~:

ekleme ikinci satır kod sorunu çözer yukarıdaki (size Clement teşekkür): Gruplara Müşterilerden ilişki için private Groups groups;:

Root<Customers> root = query.from(Customers.class); 
root.fetch(Customers_.groups, JoinType.LEFT); //that's it that's all now it will not create the extra queries 
+0

Eğer JPQL size yardımcı olup olmayacağını baktınız mı? http://stackoverflow.com/questions/2687690/jpa-2-and-hibernate-3-5-1-member-of-query-doesnt-work –

+0

MySQL veya DB2'yi kullanmak sorunun bir parçası değildir. Her nasılsa JPA, "IN (v1, v2, v3)" yerine bir projeksiyon listesindeki değerleri sorduğunuzu düşünüyor. –

+0

@James: Bu, çok daha büyük bir ölçütün çok küçük bir kısmıdır ve bu da olası kriterlerdir. – Quaternion

cevap

2

ek sorgu için nedeni bir alanını kullanarak gerçeğinden taşımaktadır. Hazırda bekletme, doğrudan alan erişimini engelleyemediğinden, bir Müşteri getirdiğinizde Gruplar nesnesini getirmelidir. N + 1 seçme tarzında (örneğin, otomatik olarak veya bir alt seçkede bir birleştirmenin yapılması yerine) ölçüt sorguları için bunu yapar.

Bunu düzeltmek için, siz de dernek getirmesi hazırda bekletme anlayabilirsiniz:

root.fetch(Customers_.groups, JoinType.LEFT); // LEFT join since your schema could have a customer with a null group. 
+0

Lütfen kelle ödülü ver. Teşekkürler. –

+0

Kabul ettikten sonra 5 saate kadar bir ödül veremediğini biliyor muydun (ya da öyle görünüyor ki ... ilk teklif ettiğimden, 2 saat daha bilmiyorum!). – Quaternion

+0

ic, benim kötü, ben de bilmiyordum. :) –

İlgili konular