Skip to main content

JPA 2 + Criteria API - Defining a subquery



I try to convert a sql query to Criteria API without success so far. I can create two separate queries which return the values I need, but I don't know how to combine them in a single query.





Here is the sql statement which works:







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;







This Criteria query returns the inner query results:







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







In the application I defined a small wrapper/helper class:







public class intCompany{

public Company comp;

public Long opentickets;

public intCompany(Long opentickets,Company comp){

this.comp = comp;

this.opentickets = opentickets;

}

public intCompany(){



}

}







So does anyone has an idea how to get this working?


Comments

  1. You have almost everything done.

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


    This should work as expected.

    ReplyDelete

Post a Comment

Popular posts from this blog

Why is this Javascript much *slower* than its jQuery equivalent?

I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later): $('#filter').keyup( function() { var jqStart = (new Date).getTime(); var search = $(this).val().toLowerCase(); var $list = $('ul.ablist > li'); $list.each( function() { if ( $(this).text().toLowerCase().indexOf(search) === -1 ) $(this).hide(); else $(this).show(); } ); console.log('Time: ' + ((new Date).getTime() - jqStart)); } ); However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent: document.getElementById('filter').addEventListener( 'keyup', function () { var jsStart = (new Date).getTime()...