ire*_*ick 5 hibernate criteria-api
假设我有类 User 和 UserGroup。有一个可选的 1-many 组到用户关联,并且关联是从双方映射的(UserGroup 端通过名为“members”的属性,它是一个 HashSet,User 端通过属性“group”)。
使用 Criteria API,如何查询按组成员计数排序的所有组?
(编辑)当我问这个问题时,我应该指出分页正在 SQL 中执行,所以如果可能的话,排序也应该在 SQL 中执行。
小智 5
默认情况下无法使用 Citeria API,但您可以扩展 org.hibernate.criterion.Order 类。这篇文章是关于如何扩展该类:http : //blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate-criteria-接口
我的解决方案是:
public class SizeOrder extends Order {
protected String propertyName;
protected boolean ascending;
protected SizeOrder(String propertyName, boolean ascending) {
super(propertyName, ascending);
this.propertyName = propertyName;
this.ascending = ascending;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String role = criteriaQuery.getEntityName(criteria, propertyName) + '.' + criteriaQuery.getPropertyName(propertyName);
QueryableCollection cp = (QueryableCollection) criteriaQuery.getFactory().getCollectionPersister(role);
String[] fk = cp.getKeyColumnNames();
String[] pk = ((Loadable) cp.getOwnerEntityPersister())
.getIdentifierColumnNames();
return " (select count(*) from " + cp.getTableName() + " where "
+ new ConditionFragment()
.setTableAlias(
criteriaQuery.getSQLAlias(criteria, propertyName)
).setCondition(pk, fk)
.toFragmentString() + ") "
+ (ascending ? "asc" : "desc");
}
public static SizeOrder asc(String propertyName) {
return new SizeOrder(propertyName, true);
}
public static SizeOrder desc(String propertyName) {
return new SizeOrder(propertyName, false);
}
}
Run Code Online (Sandbox Code Playgroud)
toSqlString 方法基于 org.hibernate.criterion.SizeExpression 类。(来源:http : //javasourcecode.org/html/open-source/hibernate/hibernate-3.6.0.Final/org/hibernate/criterion/SizeExpression.java.html)
用法示例:
hibernateSession.createCriteria(UserGroup.class).addOrder( SizeOrder.asc("members") ).list();
Run Code Online (Sandbox Code Playgroud)
这将列出按成员大小升序排列的用户组,其中“成员”是 UserGroup 实体中的用户集合。
小智 2
另一种选择是使用 @Formula 注释,它基本上相当于创建一个嵌套选择,以便您可以进行计数。
在有问题的数据库对象属性/成员(您应该创建)上,将注释添加到 getter,如下所示:
@Formula("(SELECT COUNT(TABLE_NAME.ID) FROM TABLE WHERE 不管...)") public long getNewProperty{ return newProperty; }
然后直接定位该成员以获取您的计数值...
注意:请注意,在公式注释中指定 sql 时,在引用当前对象表(this)时必须直接指定字段名称,因为 hibernate 会自行处理此问题。因此,在 WHERE 子句中,在引用当前对象表(我怀疑是 UserGroup)时,只需使用 ID 或其他任何内容。
我必须为我的新属性设置一个设置器,以便休眠功能正常工作并防止编译器抱怨。
可能还有其他聪明的方法来使用 @Formula,但我对此很陌生,并且似乎没有关于该主题的太多文档......
如果您以前从未使用过嵌套 SELECTS,那么您可能首先在 sql 中重新创建 - 这对我有帮助。
希望这可以帮助
| 归档时间: |
|
| 查看次数: |
3579 次 |
| 最近记录: |