有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用Hibernate条件实现这个多重选择和where查询?

我遇到了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查询

提前谢谢


共 (2) 个答案

  1. # 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();
    
  2. # 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语法中起到了更好的作用

    N.B.假设每个名称和服务器最多有一条记录。这可以通过(名称、服务器)上的唯一密钥强制执行

    这个假设是基于原始查询中的条件WHERE {bob server row starttime} < SELECT {alice server row starttime},如果SELECT可以返回多行,这就没有意义了