[英]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: 表
DataStatus
数据如下所示:
|-------------|--------------|--------------|---------------------|
| 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. 提前致谢。
I'm not familiar with Hibernate, but you can rewrite the query to avoid the subselect 我不熟悉Hibernate,但是您可以重写查询以避免子选择
SELECT bob.* /** Only include cols from Bob records */
FROM DataStatus bob
/** Only include rows with a later Alice record on the same server */
JOIN DataStatus alice
ON alice.name = 'Alice'
AND alice.server = bob.server
AND alice.starttime > bob.starttime
WHERE bob.name = 'Bob'
You may find this plays nicer with the Hibernate syntax 您可能会发现,使用Hibernate语法会更好
NB This assumes that you have a maximum of one record per name and server. 注意:这假设每个名称和服务器最多有一个记录。 This could be enforced by a UNIQUE KEY on (name,server)
这可以通过(name,server)上的UNIQUE KEY强制执行
This assumption is based on the condition WHERE {bob server row starttime} < SELECT {alice server row starttime}
from your original query, which doesn't really make sense if the SELECT can return more than one row 此假设基于条件
WHERE {bob server row starttime} < SELECT {alice server row starttime}
,如果SELECT可以返回多个行,则没有任何意义
My advice is to keep trying, look more in the Javadocs, experiment in your IDE. 我的建议是继续尝试,在Javadocs中查找更多内容,在IDE中进行实验。 And if you give up, try the below (assuming your table is modeled in class
DataStatus
): 如果您放弃了,请尝试以下操作(假设您的表在
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();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.