假設我有類User和UserGroup。有一個可選的一對多用戶關聯組,並且該關聯從兩側映射(UserGroup一側通過名爲「members」的屬性,這是一個HashSet,用戶端通過屬性「group」)。Hibernate Criteria API - 如何按集合大小進行排序?
使用Criteria API,我如何查詢所有組,按組成員數量排序?
(編輯)我應該指出,當我問這是在SQL中執行分頁時,所以如果可能的話,還應該在SQL中執行排序。
假設我有類User和UserGroup。有一個可選的一對多用戶關聯組,並且該關聯從兩側映射(UserGroup一側通過名爲「members」的屬性,這是一個HashSet,用戶端通過屬性「group」)。Hibernate Criteria API - 如何按集合大小進行排序?
使用Criteria API,我如何查詢所有組,按組成員數量排序?
(編輯)我應該指出,當我問這是在SQL中執行分頁時,所以如果可能的話,還應該在SQL中執行排序。
另一種選擇是使用@Formula註釋這基本上是創建一個嵌套查詢相當於這樣你就可以在得到你的數量。 FROM表
@Formula(「(SELECT COUNT(TABLE_NAME.ID)其中任何..:
在你的數據庫對象的問題屬性/件(你應該創建),添加註釋到吸氣劑像。)「) public long getNewProperty {return}返回newProperty; }
然後直接針對會員,讓您的計數值的保持......
注:請注意,指定公式註釋中的SQL時,必須直接引用當前時指定的字段名對象表(這個)作爲hibernate處理這個本身。因此,在你的WHERE子句中,當引用當前對象表時,我只能使用ID或其他任何東西,我懷疑這是UserGroup。
爲了讓hibernate工作並防止編譯器投訴,我必須爲我的新屬性設置一個setter。
有可能是使用@Formula其他聰明的方式,但我很新的這一點,似乎沒有要上受到非常多的文檔......
如果你從來沒有使用過之前嵌套的SELECTS,這可能是你首先在sql中重新創建的想法 - 幫助了我。
希望這有助於
您可以通過在您的實體上定義一個「派生屬性」,這可能是一個只讀屬性,它返回該實體內部集合的大小。定義派生屬性的最簡單的方法是documented here:
更新,insert(可選 - 默認爲 真):指定對應的 列應該包含在SQL UPDATE和/或INSERT語句。 將兩者都設置爲false允許從映射到相同列的某個其他屬性 初始化純粹的 「衍生」屬性,其值爲 ,或者通過觸發器或其他應用程序由 初始化。
一旦定義了屬性,您應該能夠在標準API中將屬性名稱用作訂單子句,就像任何其他屬性一樣。雖然我沒有嘗試過這個。
如果有效,它可能會作爲內存排序完成,因爲它無法將其映射到SQL。如果這是一個問題,那麼上面的文件相同的鏈接如何使用自定義SQL片段實現一個派生的特性:
一個強大的功能是派生 性能。這些屬性是由 定義爲只讀。 值是在加載時計算的。您 將計算聲明爲SQL 表達式。然後,這轉化爲在SQL 查詢 SELECT子句子查詢加載一個實例:
這是不可能通過使用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-api
我sollution是:
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);
}
}
的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();
這將列出了由部件的上升的大小,其中,「成員」是在用戶集合中的用戶組實體排序的用戶組。
雖然這個實現看起來有點可疑(根據hibernate文檔),但它確實可行! – ireddick 2010-03-25 14:18:55