2012-01-13 38 views
5

Tôi cố chuyển đổi truy vấn sql thành API tiêu chí mà không thành công cho đến thời điểm này. Tôi có thể tạo hai truy vấn riêng biệt trả về các giá trị tôi cần, nhưng tôi không biết cách kết hợp chúng trong một truy vấn đơn lẻ.JPA 2 + API tiêu chí - Xác định truy vấn phụ

Đây là câu lệnh SQL mà hoạt động:

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; 

truy vấn Tiêu chuẩn này sẽ trả về kết quả truy vấn bên trong:

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(); 

Trong ứng dụng tôi định nghĩa một lớp wrapper/helper nhỏ:

public class intCompany{ 
    public Company comp; 
    public Long opentickets; 
    public intCompany(Long opentickets,Company comp){ 
     this.comp = comp; 
     this.opentickets = opentickets; 
    } 
    public intCompany(){ 

    } 
} 

Vì vậy, có ai có ý tưởng về cách làm việc này không?

Cập nhật

Cảm ơn bạn. Tôi đã thay đổi truy vấn tiêu chí của mình như bạn đã đề xuất. Tôi chỉ cần thêm một vòng lặp ở cuối để có được thông tin tôi muốn.

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; 

Có thể bạn không thể chuyển đổi sql ban đầu thành API tiêu chí.

Một cập nhật

tôi đã tìm ra tôi đã phải thay đổi biểu thức sql gốc để

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; 

Nếu tôi không nhận được các công ty không có mục trong bảng vé.

Vì vậy, có đề xuất nào khác không?

Trả lời

2

Bạn gần như đã hoàn thành mọi thứ.

//---// 
CriteriaBuilder cb = em.getCriteriaBuilder(); 
//Your Wrapper class constructor must match with multiselect arguments 
CriteriaQuery<IntCompany> cq = cb.createQuery(IntCompany.class); 
//Main table 
final Root<Ticket> fromTicket= cq.from(Ticket.class); 
//Join defined in Ticket Entity 
final Path company = fromTicket.get("company"); 
//Data to select 
cq.multiselect(cb.count(from), company); 
//Grouping 
cq.groupBy(company); 
//Restrictions (I don't really understand what you're querying) 
Predicate p = cb.lessThan(fromTicket.get("state"), 16); 
//You can add more restrictions 
// p = cb.and/or(p, ...); 
cq.where(p); 
List<IntCompany> results = entityManager.createQuery(cq).getResultList(); 

Điều này sẽ hoạt động như mong đợi.

2

Tôi gặp sự cố tương tự. Giải pháp của tôi là sử dụng các kết nối bên ngoài bên trái.

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) 
)); 

này JoinType.LEFT đảm bảo rằng bạn sẽ nhận được hồ sơ Entity (công ty) ngay cả khi nó không có bất kỳ thực thể con (vé).

Entity lớp:

@Entity 
public class Entity { 
    ... 

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

    ... 
} 

mô hình tĩnh:

@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; 
} 
Các vấn đề liên quan