2012-01-29 20 views
5

JPA'da yeniyim ve genel bir JPA DAO uygulamak istiyorum ve sayfalandırma uygulamak için bir sorgu sonucunun satır sayısını bulmak gerekiyor. Web'de arama yaptıktan sonra, bunu yapmanın pratik bir yolunu bulamıyorum. join kullanırkenGenel bir JPA DAO'da JPA 2 Kriteri Sorgusunun satır sayısı nasıl sayılır?

public <T> Long findCountByCriteria(CriteriaQuery<?> criteria) { 
    CriteriaBuilder builder = em.getCriteriaBuilder(); 

    CriteriaQuery<Long> countCriteria = builder.createQuery(Long.class); 
    Root<?> entityRoot = countCriteria.from(criteria.getResultType()); 
    countCriteria.select(builder.count(entityRoot)); 
    countCriteria.where(criteria.getRestriction()); 

    return em.createQuery(countCriteria).getSingleResult(); 
} 

Ancak bu kod çalışmaz: Burada birçok makalelerinde öne koddur. JPA Ölçüt API'sini kullanarak bir sorgu sonucu kümesinin satırlarını saymanın bir yolu var mı? GÜNCELLEME

: Burada CriteriaQuery oluşturmak kodudur:

CriteriaQuery<T> queryDefinition = criteriaBuilder.createQuery(this.entityClass); 
    Root<T> root = queryDefinition.from(this.entityClass); 

ve bazı sorgu idam edilene kadar köküne eklenebilir katılır:

public Predicate addPredicate(Root<T> root) { 
       Predicate predicate = getEntityManager().getCriteriaBuilder().ge(root.join(Entity_.someList).get("id"), 13); 
       return predicate; 
} 

ve oluşturulan istisna gibi:

org.hibernate.hql.ast.QuerySyntaxException: Geçersiz yol: 'generatedAlias1.id [entity.Entity den generatedAlias0 sıra seçimi sayısı (generatedAlias0) (generatedAlias0.id> = 13L) ve ( (generatedAlias1.id < = 34L))]

olan generatedAlias1 gerektiği Varlık üzerinde olmalı ve generateAlias0 üzerinde katıldığım dernek üzerinde olmalıdır. Düzgün uyguladığınıza dikkat edin çünkü sayım sorgusu olmadan sorguyu çalıştırdığımda hata olmadan çalışır ve Birleştir düzgün çalışır ancak sayım sorgusunu çalıştırmayı denediğimde istisna atar.

+0

Kriteri nasıl güncellediniz? CriteriaQuery ölçüt – perissf

+0

@perissf Gönderiyi güncelledim mi? – stacker

+0

Benzer sorunlara başka yanıtları gözden geçirin: http://stackoverflow.com/questions/9001289/jpa-hibernate-criteriabuilder-how-to-create-query-using-relationship-object/9002225#9002225 ve http: // stackoverflow.com/questions/9025196/how-to-use-jpa-criteria-api-when-joining-many-tables/9025656#9025656 – perissf

cevap

1

Sorununuzun nerede olduğunu size söyleyemem, ancak en azından eclipselink jpa'da, katılımla birlikte sorguların sayımının iyi çalıştığını söyleyebilirim. Benim tahminim bu standart şeyler, bu yüzden de hazırda bekletmek gerekir. Sorunun nerede olduğunu yakalamak için kodunuzu basitleştirerek başlarım. Sorgu içeriğinizin bazı parçalarını ana sorgunuzdan kopyaladığınızı görüyorum. Belki de sadece hata ayıklama amacıyla bu yaklaşımı biraz değiştirmeyi deneyebilirsiniz.

Ne zaman yaptığım geçerli:

CriteriaQuery cqCount = builder.createQuery(); 
Root<T> root = cq.from(T.class); 
cqCount.select(builder.count(root)); 
ListJoin<T, Entity> join = root.join(T_.someList); 
Predicate predicate = builder.ge(join.get(Entity_.id), "myId"); 
cqCount.where(predicate); 
TypedQuery<Long> q = em.createQuery(cqCount); 

sizin sözde kod bakıldığında katılmak yönteminde yanlış sınıfını kullandığınız görülüyor: o başlangıç ​​sınıfı değil, hedef sınıfı olmalıdır. Onun için şeref - lubo08 @

+0

İyi bir geceden sonra basit cevabınızı okuduktan sonra 10 saatlik bir mücadeleden çıktım. Bu birleştirme sorgusu ve kriterleri ile ...:) – Raindal

6

Bunu yaptım . Ancak iki köşe durumlar için onun/onu kod çalışmaz:

  • kriter sorgunun kısıtlamalar katılır takma adlarını kullandığınızda - o zaman COUNT da ayarlanması bu takma adlar gerektirir.Hala olmasına rağmen

    public <T> long count(final CriteriaBuilder cb, final CriteriaQuery<T> criteria, 
         Root<T> root) { 
        CriteriaQuery<Long> query = createCountQuery(cb, criteria, root); 
        return this.entityManager.createQuery(query).getSingleResult(); 
    } 
    
    private <T> CriteriaQuery<Long> createCountQuery(final CriteriaBuilder cb, 
         final CriteriaQuery<T> criteria, final Root<T> root) { 
    
        final CriteriaQuery<Long> countQuery = cb.createQuery(Long.class); 
        final Root<T> countRoot = countQuery.from(criteria.getResultType()); 
    
        doJoins(root.getJoins(), countRoot); 
        doJoinsOnFetches(root.getFetches(), countRoot); 
    
        countQuery.select(cb.count(countRoot)); 
        countQuery.where(criteria.getRestriction()); 
    
        countRoot.alias(root.getAlias()); 
    
        return countQuery.distinct(criteria.isDistinct()); 
    } 
    
    @SuppressWarnings("unchecked") 
    private void doJoinsOnFetches(Set<? extends Fetch<?, ?>> joins, Root<?> root) { 
        doJoins((Set<? extends Join<?, ?>>) joins, root); 
    } 
    
    private void doJoins(Set<? extends Join<?, ?>> joins, Root<?> root) { 
        for (Join<?, ?> join : joins) { 
         Join<?, ?> joined = root.join(join.getAttribute().getName(), join.getJoinType()); 
         joined.alias(join.getAlias()); 
         doJoins(join.getJoins(), joined); 
        } 
    } 
    
    private void doJoins(Set<? extends Join<?, ?>> joins, Join<?, ?> root) { 
        for (Join<?, ?> join : joins) { 
         Join<?, ?> joined = root.join(join.getAttribute().getName(), join.getJoinType()); 
         joined.alias(join.getAlias()); 
         doJoins(join.getJoins(), joined); 
        } 
    } 
    

    : şeyiyle Yani

[root.fetch(..) yerine root.join(..) ait] kriterleri sorgu kullanımı katılmak getirme

  • Ben mevcut aşağıda onun/onu çözümünü ve geliştirmek için cesaret mükemmel değil, çünkü sadece bir kök onurlandırıldı.
    Ama umarım birilerine yardım eder.

  • +0

    Güzel cevap, işinizi paylaştığınız için teşekkürler. –

    3

    doğru cevap verdi

    Eğer ölçüt sorgudan bunu alabilir girdi parametresi olarak Kök gerekmez elbette
    public Long getRowCount(CriteriaQuery criteriaQuery,CriteriaBuilder criteriaBuilder,Root<?> root){ 
        CriteriaQuery<Long> countCriteria = criteriaBuilder.createQuery(Long.class); 
        Root<?> entityRoot = countCriteria.from(root.getJavaType()); 
        entityRoot.alias(root.getAlias()); 
        doJoins(root.getJoins(),entityRoot); 
        countCriteria.select(criteriaBuilder.count(entityRoot)); 
        countCriteria.where(criteriaQuery.getRestriction()); 
        return this.entityManager.createQuery(countCriteria).getSingleResult(); 
    } 
    
    private void doJoins(Set<? extends Join<?, ?>> joins,Root<?> root_){ 
        for(Join<?,?> join: joins){ 
         Join<?,?> joined = root_.join(join.getAttribute().getName(),join.getJoinType()); 
         doJoins(join.getJoins(), joined); 
        } 
    } 
    
    private void doJoins(Set<? extends Join<?, ?>> joins,Join<?,?> root_){ 
        for(Join<?,?> join: joins){ 
         Join<?,?> joined = root_.join(join.getAttribute().getName(),join.getJoinType()); 
         doJoins(join.getJoins(),joined); 
        } 
    } 
    

    :