2013-07-05 102 views
1

我的代碼是:ORA-01791 Hibernate查詢

Criteria criteriaA = getHibernateSession().createCriteria(entityA.class, "aaa"); 
Criteria criteriaB = criteriaA.createCriteria("entityB").setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); // It seems that the result transformer don't affect the code... 

criteriaA.add(-- some restriction --) 

if (orderById) { 
    criteriaB.addOrder(Order.desc("id")); 
} 

if (!orderById && orderByDate) { 
    criteriaB.addOrder(Order.desc("date")); 
} 

criteriaA.setProjection(Projections.distinct(Projections.property("entityB"))); 

entityA和entityB有一個一對多扯上關係(一個entityB可以有0 .. * entityA),但我可以從只有B轉到A(限制項目..不能改變這一點)。
現在,問題是我不需要重複的結果返回,我需要排序我的結果。
奇怪的事實是,ORA-01791(它告訴我,有一個不正確的orderby)我只在按日期排序時啓動,按id排序不會給我任何問題,但都是我想要區分的實體的屬性!
爲什麼我可以按ID排序但不是按日期?
是否有另一種方法來做我想做的事情?

----編輯-----
正如莫比建議我看着生成的查詢:

DEBUG [org.hibernate.SQL] 
select distinct this_.BBB_ID as y0_ 
from TB_ENTITY_A this_ 
inner join TB_ENTITY_B entityB_ on this_.BBB_ID=entityB_.BBB_ID 
where this_.ANOTHER_ID=? and lower(this_.AAA_VALUE) like ? and this_.AAA_ID in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
order by entityB_.BBB_DATE asc 

所以,我分明只有外鍵的ID應用..
我如何強制Hibernate選擇所有的字段?
如果我做的:

criteriaB.list(); 

,而不是

criteriaA.list(): 

我將失去從criteriaA過濾器?
我在想也試圖在Projection中設置所有來自entityB的字段,但我不確定hibernate是否可以將結果轉換爲實體。

+0

+1爲解決方案,是我自己會提出一個子選擇。你也可以把它當作自己的答案。 – mabi

+0

對,現在我已經完成:) –

回答

0

由於金馬碧建議我回答我的問題後我的解決方案:

---- -----解決

我改變了我在組織查詢的方式:我創建分離標準爲衆多端實體和一個子查詢檢索其他實體:

DetachedCriteria criteriaA = DetachedCriteria.forClass(EntityA.class, "aaa"); 
criteriaA.add(-- some restriction --); 
criteriaA.setProjection(Projections.property("entityB")); 

Criteria criteriaB = getHibernateSession().createCriteria(EntityB.class, "bbb"); 
criteriaB.add(Property.forName("id").in(criteriaA)); 

,所以我並不需要一個獨特的和可以排序的所有領域,我從實體想B.

2

http://ora-01791.ora-code.com/說:

在這種情況下,所有的ORDER BY項目必須是常量,SELECT列表 表達式或表達式,其操作數是常數或選擇 列表表達式

我猜測你/冬眠不選擇date。如果你這樣做,你可以將生成的SQL添加到問題中嗎?

+0

在正常情況下,它應該可以工作,但是在這種特殊情況下,通過使用DISTINCT,查詢規劃器不知道它將選擇哪一行,因此無法使用日期作爲訂購。 –

0

對錶或字段名稱使用SQL關鍵字時會出現奇怪的問題。這可能是這裏發生的事情。只要嘗試將@Column(name = "date_")放在您的實體屬性上即可。

+0

已有: @ javax.persistence.Column(name =「AAA_DATE」,nullable = false,insertable = true,updatable = true) @ javax.persistence.Temporal(javax.persistence.TemporalType.TIMESTAMP) public Java .util.Date getDate() { return date; } –

+0

我也說所有的實體屬性都註釋到表字段 –

0

瑪比在他/她的猜測中是正確的。

你想要做的是產生一個查詢,看起來像這樣:

select this_.BBB_ID as y0_, min(entityB_.BBB_DATE) as min_date 
from TB_ENTITY_A this_ 
inner join TB_ENTITY_B entityB_ on this_.BBB_ID=entityB_.BBB_ID 
where this_.ANOTHER_ID=? and lower(this_.AAA_VALUE) like ? 
    and this_.AAA_ID in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
group by this_.BBB_ID 
order by min_date asc 

不知道怎麼做,在休眠雖然。

然而,如果Hibernate無法與兩列管理返回取的ID,這樣的查詢應該工作:

select y0_ 
    from(
     select this_.BBB_ID as y0_, min(entityB_.BBB_DATE) as min_date 
      from TB_ENTITY_A this_ 
       inner join TB_ENTITY_B entityB_ on this_.BBB_ID=entityB_.BBB_ID 
      where this_.ANOTHER_ID=? and lower(this_.AAA_VALUE) like ? 
       and this_.AAA_ID in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
      group by this_.BBB_ID 
    ) a 
order by min_date asc 

但同樣,如何做到這一點在Hibernate中,我沒有任何線索。它認爲可以添加自定義SQL/HQL,所以你應該能夠以某種方式創建它。

+0

但是讓我們假設用hibernate來實現這個查詢,我的疑問是:如果在第一個查詢中hibernate使用返回給查詢的id並且恢復實體,如果我用ID和日期做了一個查詢,可以休眠一樣嗎? –

+0

好問題。我並不精通Hibernate,所以我不能說 –

+0

這很有趣,我也不知道如何得到這樣的查詢,但是我發現返回的結果沒有輸入,所以通過向條件添加正確的投影命令criteriaB.list()沒有拋出任何異常,但是用前面的sql它能夠將對象返回給entityA,而使用投影技巧則拋出失敗。 –