2011-06-16 27 views
2

爲什麼Hibernate的抱怨以下查詢:Hibernate的假設在HQL查詢參數那裏有沒有

public Set<Long> findImageVariantIdsWithOutOfBoundsDimension() { 
    final StringBuilder queryBuilder = new StringBuilder(); 
    queryBuilder.append("select id from ImageVariant where "); 
    // imageVariantType is something like R_110X75 with 110 being max x. 
    // cast(substring(extracts 110. 
    queryBuilder.append("dimensionX > cast(substring(imageVariantType, 3, locate('X', imageVariantType) - 3), int) "); 
    queryBuilder.append("or "); 
    // imageVariantType is something like R_110X75 with 75 being max y. 
    // cast(substring(extracts 75. 
    queryBuilder.append("dimensionY > cast(substring(imageVariantType, locate('X', imageVariantType) + 1), int)"); 
    final Query query = getEntityManager().createQuery(queryBuilder.toString()); 
    @SuppressWarnings("unchecked") 
    final Set<Long> result = new HashSet<Long>(query.getResultList()); 
    return result; 
    } 

警告是Function template anticipated 3 arguments, but 2 arguments encountered。但是,我的查詢既不包含標記也不包含參數。由於cast是一個Hibernate特有的函數(JPQL中沒有字符串到int的轉換),我認爲這是一個HQL問題。

當我調試休眠的TemplateRenderer我看到它的內部參數列表是['X', imagevaria0_.imagevarianttype]

+0

一些什麼類似的問題http://solitarygeek.com/java/extracting-only-date-part-of-a-date-time-column-using-jpa-hibernate – Reddy 2011-06-27 15:10:09

回答

3

這基本上是Hibernate的警告說,一些SQL函數沒有被調用,它的所有允許的參數。在你的情況下,這是LOCATE函數。該函數的語法是LOCATE(string1, string 2, [start]),其中start是一個可選參數,用於指定從何處開始搜索的第一個字符的索引。

在你的情況,你調用這個函數作爲locate('X', imageVariantType),通過它只有兩個參數,而不是允許的最大3。休眠類TemplateRenderer檢測到這一點並生成您看到的警告消息。

我曾提出一個bug使用Hibernate的球隊要麼降低這個消息的嚴重性(因爲它不正確地在大多數情況下停止工作查詢)或執行它周圍的更好的檢查,從而使警報沒有得到在對給定的SQL函數有效的情況下生成。

至於運行到類似的問題的人,這樣的警告可以簡單,如果查詢工作正常忽略。

1

當你知道它是休眠特定的功能你爲什麼要使用JPA創建查詢?

嘗試讓Hibernate的Session,並在其上創建查詢。您可以使用

Session session = (Session) em.getDelegate(); 

編輯得到Hibernate的Session:getEntityManager()的createQuery(queryBuilder.toString()); 假設您傳遞的查詢字符串是JPQL嗎?您不應該在此使用HQL特定功能。 您需要獲取HQL會話而不是JPA實體管理器來創建查詢。

編輯:我嘗試這樣做,這是對我工作的罰款。我的配置是使用Hibernate 3.6.0和MySQL 5.1.28的JPA 2.0。你的配置是什麼? -

+0

對不起,我不太瞭解你的回答。你建議使用查詢API嗎? – 2011-06-16 19:19:03

+0

更新了票證。 – Reddy 2011-06-17 05:26:40

+0

不,您可以將HQL字符串傳遞給createQuery()方法,因爲您獲得的EM實例是Hibernate實體管理器。從Hibernate 3開始JPQL是HQL的一個子集。 – 2011-06-17 08:39:45