我在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错误消息:
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()也是可以接受的,但是编写该查询的成功率甚至更低。
s.createSQLQuery()
s.createQuery()
在Criteria您提供的似乎只产生内部查询部分。您可以组合内部查询,例如通过使用DetachedCriteria:
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查询,createSQLString如果希望在结果查询中使用显式列名,则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();