2012-01-13 8 views
5

Şimdiye kadar başarı olmadan bir sql sorgusunu Kriter API'sına dönüştürmeyi deniyorum. İhtiyacım olan değerleri döndüren iki ayrı sorgu oluşturabilirim, ancak bunları tek bir sorguda nasıl birleştireceğimi bilmiyorum.JPA 2 + Kriter API - Bir alt sorgunun tanımlanması

: Ben küçük bir sarmalayıcı/yardımcı sınıf tanımlı uygulamasında

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<intCompany> qTicket = cb.createQuery(intCompany.class); 
Root<Ticket> from = qTicket.from(Ticket.class); 
Path groupBy = from.get("company");   
Predicate state = cb.notEqual(from.<State>get("state"), getStateById(16));   
qTicket.select(cb.construct(
    intCompany.class, cb.count(from),from.<Company>get("company"))) 
     .where(state).groupBy(groupBy);     
em.createQuery(qTicket).getResultList(); 

:

select company.*, ticketcount.counter from company 
    join 
(select company, COUNT(*) as counter from ticket where state<16 group by company) ticketcount 
on company.compid = ticketcount.company; 

Bu Kriterler sorgusu iç sorgu sonuçları verir: Burada

çalışır sql ifadesi
public class intCompany{ 
    public Company comp; 
    public Long opentickets; 
    public intCompany(Long opentickets,Company comp){ 
     this.comp = comp; 
     this.opentickets = opentickets; 
    } 
    public intCompany(){ 

    } 
} 

Peki, bu çalışmayı nasıl alacağına dair bir fikri olan var mı?

Güncelleme teşekkür ederiz. Kriterlerimi önerdiğin gibi değiştirdim. Sonunda istediğim bilgiyi almak için bir döngü eklemem gerekiyordu.

List<intCompany> result = em.createQuery(cq).getResultList(); 
List<Company> cresult = new ArrayList(); 
    for(intCompany ic: result){ 
     ic.comp.setOpentickets(ic.opentickets.intValue()); 
     cresult.add(ic.comp); 
    } 
return cresult; 

Belki Kriterler API orijinal sql dönüştürmek için sadece mümkün değildir.

ben Aksi takdirde bilet tabloda hiç girişlerle şirketleri alamadım

select company.*, ticketcount.counter from company 
    left join 
(select company, COUNT(*) as counter from ticket where state<16 group by company) ticketcount 
on company.compid = ticketcount.company; 

orijinal sql ifadesini değiştirmek zorunda anladım

Diğer bir güncelleme.

Başka önerileriniz var mı?

cevap

2

Neredeyse her şey bitti. Bu, beklendiği gibi çalışmalıdır.

2

Benzer bir sorun yaşadım. Benim çözümüm sol dış birleşimleri kullanmaktı.

CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Entity> query = cb.createQuery(Entity.class); 
Root<Entity> root = query.from(Entity.class); 

Join<Entity,ChildEntity> join = root.join(Entity_.children, JoinType.LEFT); 
query.groupBy(root.get(Entity_.id)); 
query.select(
    cb.construct(
    EntityDTO.class, 
    root.get(Entity_.id), 
    root.get(Entity_.name), 
    cb.count(join) 
)); 

herhangi çocuk varlıkları (bilet) olmasa bile eğer varlık kayıtları (şirketleri) alacak Bu JoinType.LEFT garanti eder.

Varlık sınıfı:

@Entity 
public class Entity { 
    ... 

    @OneToMany(targetEntity = ChildEntity.class, mappedBy = "parent", fetch = FetchType.LAZY, orphanRemoval = false) 
    private Set<ChildEntity> objects; 

    ... 
} 

Statik modeli:

@StaticMetamodel(Entity.class) 
public class Entity_ { 
    public static volatile SingularAttribute<Entity, Long> id; 
    public static volatile SingularAttribute<Entity, String> name; 
    ... 
    public static volatile SetAttribute<Entity, ChildEntity> objects; 
} 
İlgili konular