使用 Max() 投影对键字段和按外主键分组的 Hibernate 条件查询

标签 hibernate group-by projection foreign-keys many-to-one

我很难将此查询(直接在数据库上工作)表示为 Hibernate(3.2.5 版)中的条件查询:

SELECT s.* 
  FROM ftp_status s 
 WHERE (s.datetime,s.connectionid) IN (SELECT MAX(f.datetime),
                                              f.connectionid 
                                         FROM ftp_status f
                                        GROUP BY f.connectionid);

到目前为止,这是我想出的不起作用的方法,并抛出了 could not resolve property: datetime of: common.entity.FtpStatus错误信息:
Criteria crit = s.createCriteria(FtpStatus.class);
crit = crit.createAlias("connections", "c");
crit = crit.createAlias("id", "f");
ProjectionList proj = Projections.projectionList();
proj = proj.add(Projections.max("f.datetime"));
proj = proj.add(Projections.groupProperty("c.connectionid"));
crit = crit.setProjection(proj);
List<FtpStatus> dtlList = crit.list();

下面是Netbeans 6.8直接从数据库生成的相关引用配置:

FtpStatus.hbm.xml -
<hibernate-mapping>
   <class name="common.entity.FtpStatus" table="ftp_status" catalog="common">
        <composite-id name="id" class="common.entity.FtpStatusId">
            <key-property name="siteid" type="int">
                <column name="siteid" />
            </key-property>
            <key-property name="connectionid" type="int">
                <column name="connectionid" />
            </key-property>
            <key-property name="datetime" type="timestamp">
                <column name="datetime" length="19" />
            </key-property>
        </composite-id>
        <many-to-one name="connections" class="common.entity.Connections" update="false" insert="false" fetch="select">
            <column name="connectionid" not-null="true" />
        </many-to-one>
        <many-to-one name="sites" class="common.entity.Sites" update="false" insert="false" fetch="select">
            <column name="siteid" not-null="true" />
        </many-to-one>
        <property name="upInd" type="boolean">
            <column name="up_ind" not-null="true" />
        </property>
        <property name="lastMessage" type="string">
            <column name="last_message" length="65535" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

Connections.hbm.xml -
<hibernate-mapping>
    <class name="common.entity.Connections" table="connections" catalog="common">
        <id name="connectionid" type="java.lang.Integer">
            <column name="connectionid" />
            <generator class="identity" />
        </id>
        <property name="ip" type="string">
            <column name="ip" length="15" not-null="true" />
        </property>
        <property name="port" type="int">
            <column name="port" not-null="true" />
        </property>
        <property name="user" type="string">
            <column name="user" length="8" not-null="true" />
        </property>
        <property name="password" type="string">
            <column name="password" length="50" not-null="true" />
        </property>
        <set name="ftpStatuses" inverse="true">
            <key>
                <column name="connectionid" not-null="true" />
            </key>
            <one-to-many class="common.entity.FtpStatus" />
        </set>
    </class>
</hibernate-mapping>

我知道我遗漏了一些东西,但是我在 hibernate 上的谷歌搜索还没有发现它。或者直接使用 s.createSQLQuery() 进行 SQL 查询或 s.createQuery()也是可以接受的,但我写那个的成功更少......

最佳答案

Criteria您提供的似乎只生成内部查询部分。您可以组合内部查询,例如通过使用 DetachedCriteria :

DetachedCriteria maxDateQuery = DetachedCriteria.forClass(FtpStatus.class);
ProjectionList proj = Projections.projectionList();
proj.add(Projections.max("datetime"));
proj.add(Projections.groupProperty("connectionid"));
maxDateQuery.setProjection(proj);

Criteria crit = s.createCriteria(FtpStatus.class);
crit.add(Subqueries.propertiesEq(new String[] {"datetime", "connectionid"}, maxDateQuery));

List<FtpStatus> dtlList = crit.list();

请注意,直到 Hibernate 4.0.0.CR5 (HHH-6766) 才实现对多列子查询的支持。 .

至于原生 SQL 查询,Hibernate 的 createSQLString如果希望在结果查询中具有显式列名,则应该立即使用您指定的查询字符串或添加的查询中涉及的实体。
String queryString = "SELECT {status.*}"
                   + "  FROM ftp_status status"
                   + "  WHERE (datetime, connectionid) IN ("
                   + "    SELECT MAX(datetime), connectionid"
                   + "      FROM ftp_status"
                   + "      GROUP BY connectionid"
                   + "  )";

SQLQuery query = s.createSQLQuery(queryString).addEntity("status", FtpStatus.class);

List<FtpStatus> dtlList = query.list();

关于使用 Max() 投影对键字段和按外主键分组的 Hibernate 条件查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2723803/

相关文章:

python - 按对象将 pandas 组转换为多索引 Dataframe

opengl - opengl中的正交投影和纹理坐标

Android MapView 投影返回负数

hibernate - grails 不使用缓存

java - 创建 JUnit 测试时没有此类方法错误

java - 将Excel数据转换为MySql表

mysql - 条件组通过使用 Laravel

python - Pandas 元组 groupby 聚合

c# - 帮助 C# LINQ 投影

java - 如何使用rest api插入hibernate中的表,并且该表2列是另一个表的外键?