Search code examples
javamysqlhibernatehibernate-criteria

How to implement this multiple select and where query with Hibernate criteria?


I have faced a Hibernate criteria query issues.

Table DataStatus data looks like below:

|-------------|--------------|--------------|---------------------|
|     name    |     info     |    server    |      starttime      |
|-------------|--------------|--------------|---------------------|
|     Bob     | information1 |     www1     | 2018-02-14 10:32:43 |
|     Alice   | information2 |     www3     | 2018-02-14 17:34:43 |
|     Bob     | information3 |     www2     | 2018-02-14 10:32:43 |
|     Alice   | information4 |     www1     | 2018-02-14 11:25:51 |
|     Alice   | information5 |     www2     | 2018-02-14 08:42:25 |
|     Bob     | information6 |     www3     | 2018-02-14 10:32:43 |
|-------------|--------------|--------------|---------------------|

Query looks like this:

SELECT * FROM DataStatus sts 
WHERE sts.server IS NOT NULL 
AND sts.name = 'Bob' 
AND sts.starttime < (
   SELECT starttime FROM DataStatus 
   WHERE name = 'Alice' AND server = sts.server);

And the result looks like this:

|-------------|--------------|--------------|---------------------|
|     name    |     info     |    server    |      starttime      |
|-------------|--------------|--------------|---------------------|
|     Bob     | information1 |     www1     | 2018-02-14 10:32:43 |
|     Bob     | information6 |     www3     | 2018-02-14 10:32:43 |
|-------------|--------------|--------------|---------------------|

I have tried something like below:

Criteria criteria = session.CreateCriteria(DataStatus.class);
criteria.add(
    Restrictions.and(
        criteria.add(Restrictions.isNotNull("server")),
        criteria.add(Restrictions.eq("name", "Bob")),
        criteria.add(Restrictions.lt("starttime", ))
    )
);

I have no idea how to implement this nested where and select query with Hibernate criteria?

Thanks in advance.


Solution

  • My advice is to keep trying, look more in the Javadocs, experiment in your IDE. And if you give up, try the below (assuming your table is modeled in class DataStatus):

    CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
    CriteriaQuery<DataStatus> criteriaQuery = criteriaBuilder.createQuery(DataStatus.class);
    Root<DataStatus> root = criteriaQuery.from(DataStatus.class);
    
    Subquery<Date> subquery = criteriaQuery.subquery(Date.class);
    Root<DataStatus> innerRoot = subquery.from(DataStatus.class);
    
    subquery.select(innerRoot.get("startTime"))
            .where(criteriaBuilder.and(criteriaBuilder.equal(innerRoot.get("name"), "Alice"),
                    criteriaBuilder.equal(innerRoot.get("server"), root.get("server"))));
    
    criteriaQuery.select(root).where(
            criteriaBuilder.and( criteriaBuilder.isNotNull( root.get( "server" ) ),
                    criteriaBuilder.equal(root.get("name"), "Bob" ),
                    criteriaBuilder.lessThan(root.<Date> get("startTime"), subquery)
    
            ) );
    
    Query<DataStatus> query = session.createQuery(criteriaQuery);
    List<DataStatus> resultList = query.getResultList();