1

I have 2 tables, Partner and Visit. A partner can have many visits, also various in same day. I need to create a Criteria restriction to know how many days the Partner has visits since a given date. So, 2 or more visits in same date must be only one.

Can this be done only by Criteria and Restrictions??

I can get all visits from a date with a criteria like:

Criteria criteria = buildCriteria();
criteria.add(Restrictions.eq(DBConstants.VISIT_COL_VISITOR, partnerVisitor));
criteria.add(Restrictions.ge(DBConstants.VISIT_COL_DATE, startDate));

But now, to filter repeated days, I need something like:

criteria.add(Restrictions.unique(DBConstants.VISIT_COL_DATE));

Any idea?

EDIT: @user23123412 @netik

Visit.java

private Integer id;
private Date date;
private Partner visitor;

// getters + setters

Visit table rows related to partner 1:

ID VISITOR DATE
1 1 10/10/2014 16:20
20 1 10/10/2014 18:00
45 1 12/10/2014 16:20
71 1 12/10/2014 19:40
89 1 16/10/2014 11:20

The answer I need after the query is a Visit count in different days since a given date.

I.E.: If i launch a query with visitor = 1 and startDate = 12/10/2014 the result MUST be 2, cause row id = 45 and id = 71 have different visits in a same day, so it's only ONE day.

5
  • Yes you can achieve this using criteria, do you have oneToMany relationship on your JPA? Commented Nov 11, 2014 at 10:08
  • Yes, OneToManyrelationship is in Partner which can have many Visits... but this is not important here, Date has no relationship with Partner and can be repeated several times with different hour... Commented Nov 11, 2014 at 10:23
  • can you produce a database query that you want to achieve? Commented Nov 11, 2014 at 10:29
  • Give us some small data sample (partner, visit) and your result expectation.
    – netik
    Commented Nov 11, 2014 at 10:33
  • @netik more info attached... any ideas? :) Commented Nov 11, 2014 at 16:36

2 Answers 2

6

You have three options:

1) If you are not pinned to Critera api, I recommend to use HQL instead of Criteria API

Date d =  new SimpleDateFormat("yyyy-MM-dd").parse("2025-08-05");
Query query = session.createQuery("select count(*) from Visit v where trunc(v.date)=:date and v.visitor.id=:visitorId");
query.setParameter("date", d);
query.setParameter("visitorId", 1L);
Long count =  (Long) query.uniqueResult();

2) If you want to use Criteria API, it's possible to apply sqlRestriction. Unfortunately you will lock to specific database. This example works on HSQLDB

Date d =  new SimpleDateFormat("yyyy-MM-dd").parse("2025-08-05");
Long count = (Long) session.createCriteria(Visit.class)
           .setProjection(Projections.rowCount())
           .add(Restrictions.eq("visitor.id", 1L))
           .add(Restrictions.sqlRestriction("trunc(date)=?", d, org.hibernate.type.StandardBasicTypes.DATE))
           .uniqueResult()  ;

3) It's also possible to use pure criteria API, but date restriction must be a little bit hacked (using between restriction)

Date d =  new SimpleDateFormat("yyyy-MM-dd").parse("2025-08-05");
Date maxDate = new Date(d.getTime() + TimeUnit.DAYS.toMillis(1));
Long count = (Long) session.createCriteria(Visit.class)
                .setProjection(Projections.rowCount())
                .add(Restrictions.eq("visitor.id", 1L))
                .add(Restrictions.between("date", d, maxDate))
                .uniqueResult();
2
  • sorry for late answer @netik Commented Nov 16, 2014 at 15:36
  • I'm trying to use first option, but i get a MySQLSyntaxErrorException cause does not recognice trunc ... Commented Nov 16, 2014 at 16:46
1

Well... finally, after almost getting crazy, I've found solution to my query using @netik first solution with some modifications: I've found out problem was mysql was not supporting trunc . No matter hql does.

So finally the query method after data processing is like that:

public Integer getPartnerVisitDatesSinceDate(Date startDate, Long partnerId) {
    Query query = getSession().createQuery("select count(distinct visit.date) from Visit visit where date(visit.date) >= :date and visit.visitor.id = :visitorId");
    query.setDate("date", startDate);
    query.setParameter("visitorId", partnerId);
    return (Integer) query.uniqueResult();
}

Thanks @netik!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.