The Criteria approach is very simple and straightforward (although it has still some limitations that I had to resolve by looking into hibernate source file and ended up with creating custom order class for example; but do not be scared, everything is possible)
See a very simplified example
Code:
Session session = sessionFactory.openSession(); // create session first
Criteria criteria = session.createCriteria(CallSummary.class, "call"); // criteria will start of table CALL_SUMMARY (AS call)
criteria.createAlias("call.iface", "fc", Criteria.LEFT_JOIN); // LEFT JOIN with table IFACE (AS fc)
criteria.add(Restrictions.ne("call.duration", new Long(0))); // first filter in WHERE clause => duration is not equal to 0
Disjunction disjunction = Restrictions.disjunction(); // another filter is disjunction - logical OR
disjunction.add(Restrictions.gt("call.min", new Float(10))); // CALL_SUMMARY.min > 10
disjunction.add(Restrictions.eq("fc.label", "Interface A"); // IFACE.label="Interface A"
criteria.add(disjunction); // set another filter - logical AND with previous filter
criteria.setProjection(Projections.rowCount()); // first I am interested only in number of rows that pass
int count = ((Integer)criteria.uniqueResult()).intValue();
criteria.addOrder(Order.asc("callId")); // order by CALL_SUMMARY.callId
criteria.setMaxResults(100); // get only first 100 results
criteria.setProjection(Projections.projectionList() // set custom projection (in SQL it is the SELECT clause definition)
.add(Projections.min("score"))
.add(Projections.avg("ratio"))); // SELECT MIN(CALL_SUMMARY.score), AVG(CALL_SUMMARY.ratio)
List list = criteria.list(); // get result
Simple, isn't it?