【问题标题】:How to implement this multiple select and where query with Hibernate criteria?如何使用 Hibernate 条件实现此多项选择和查询?
【发布时间】:2019-04-07 10:06:09
【问题描述】:

我遇到了 Hibernate 条件查询问题。

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 |
|-------------|--------------|--------------|---------------------|

查询如下所示:

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

结果如下所示:

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

我尝试过类似以下的方法:

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", ))
    )
);

我不知道如何使用 Hibernate 条件实现这个嵌套的 where 和 select 查询?

提前致谢。

【问题讨论】:

  • 你确定 sql 查询有效吗,我怀疑它会返回一个错误,说子查询返回多于一行或类似的东西
  • 嗨@JoakimDanielson,我很确定SQL 是正确的。它为我返回了正确的数据。
  • @Almett 您的查询仅返回 1 行:"Bob" "information1" "www1" "2018-02-14 10:32:43"。也许您发布的数据不是实际数据。同样在您的查询中将'ALice' 更改为'Alice',除非它是拼写错误或相等不区分大小写。
  • 非常抱歉,这是“爱丽丝”而不是“爱丽丝”。我更改了 Alice(www3) 的 starttime 以使其大于 Bob(www3) 的“开始时间”。现在它返回与我相同的结果。感谢您的努力。
  • @JoakimDanielson 假设 (name, server) 是唯一的 OP 就可以了,如果不是.. 可能会出现问题!

标签: java mysql hibernate hibernate-criteria


【解决方案1】:

我的建议是继续尝试,多看 Javadocs,在你的 IDE 中试验。如果你放弃了,试试下面的方法(假设你的表是在 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();

【讨论】:

  • 这段代码运行良好。华丽的一个!太棒了!非常感谢。
  • 但它只适用于 Hibernate-5.2+。并且 createCriteria() 方法在 Hibernate-5.2+ 中已被弃用。如果有一堆标准写在createCriteria() 应该重构。无论如何,答案都很好。
【解决方案2】:

我对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'

您可能会发现这与 Hibernate 语法配合得更好

注意这假设您每个名称和服务器最多有一条记录。这可以通过 (name,server) 上的 UNIQUE KEY 强制执行

此假设基于原始查询中的条件WHERE {bob server row starttime} &lt; SELECT {alice server row starttime},如果 SELECT 可以返回多行,则这实际上没有意义

【讨论】:

  • 嗨@Arth,感谢您的努力。是的,它适用于 Hibernate 语法,但我的项目要求是使用 Hibernate Criteria。您对这个问题的深刻思考看起来非常令人印象深刻,我将尝试根据您的提示重新设计 SQL。谢谢!
  • @Almett 乐于助人!我的意思是这可能会更好地与 Hibernate Criteria 配合使用。根据我对 PHP 框架的经验,JOIN 似乎比子查询更受支持。话虽如此,这只是对更复杂的答案的补充,但太丰富了,无法发表评论!
猜你喜欢
  • 1970-01-01
  • 2014-09-11
  • 2015-04-04
  • 2018-09-28
  • 2012-12-01
  • 2011-12-07
  • 1970-01-01
  • 2019-01-16
相关资源
最近更新 更多