2014-12-27 31 views
1

我正在開發一個Java應用程序,最近一位同事告訴我,如果我爲我的一些需求使用存儲過程,我的解決方案將變得更整齊。我開始閱讀他們,他們看起來很有希望,但現在我很難讓Hibernate將從這種存儲過程返回的結果映射到java bean。將PostgreSQL的refcursor映射到使用Hibernate的java實體

這裏是我試圖去的過程:

CREATE OR REPLACE FUNCTION wrong_user_answers(testId INTEGER, userId INTEGER) RETURNS refcursor AS $wrong_user_answers$ 
    DECLARE 
     ref refcursor; 
    BEGIN 
     OPEN ref FOR SELECT ua.* 
     FROM t_tests as t 
     JOIN t_user_answers as ua on ua.fk_test_id = t.pk_test_id 
     WHERE t.pk_test_id = testId and ua.fk_user_id = userId and is_correct(ua) = false; 
     RETURN ref; 
    END; 
    $wrong_user_answers$ LANGUAGE plpgsql; 

這裏is_correct(ua)是我定義的另一個存儲過程。我已經在PGAdmin中嘗試過這個過程,並且它完全返回我所期望的 - 包含用戶答案的​​refcursor。

這裏是我認爲應該得到這一切滾動代碼的Java的一部分:

附加註釋(@NamedNativeQuery)在UserAnswerBean

@NamedNativeQueries({ 
     @NamedNativeQuery(name = "getWrongUserAnswers", 
         query = "select wrong_user_answers(:testId, :userId)", 
         resultClass = UserAnswerBean.class) 
}) 
@Entity 
@Table(name = "t_user_answers") 
public class UserAnswerBean { 

和使用該程序的代碼:

Query query = getEntityManager().createNamedQuery("getWrongUserAnswers"); 
query.setParameter("testId", testId); 
query.setParameter("userId", userId); 
List<UserAnswerBean> answers = query.getResultList(); 

當接收到上下面erorr上述最後一行代碼執行的嘗試:

org.postgresql.util.PSQLException:列名pk_user_answer_id 並沒有到此ResultSet中。 org.postgresql.jdbc2.AbstractJdbc2ResultSet.findColumn(AbstractJdbc2ResultSet.java:2728) org.postgresql.jdbc2.AbstractJdbc2ResultSet.getInt(AbstractJdbc2ResultSet.java:2589) org.hibernate.type.descriptor.sql.IntegerTypeDescriptor $ 2.doExtract( IntegerTypeDescriptor.java:74) org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64) org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:267) org.hibernate.type .AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:263) org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:338) org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:784) org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:720) org.hibernate.loader.Loader.processResultSet(Loader.java:952 )

我不知道如何在這裏繼續,我無法在互聯網上找到任何有用的資源。所以,我認爲這個問題是,我是返回REFCURSOR,選擇的不是立即的結果,所以我改變了存儲過程來:

CREATE OR REPLACE FUNCTION wrong_user_answers(testId INTEGER, userId INTEGER) RETURNS setof record AS $wrong_user_answers$ 
    SELECT ua.* 
     FROM t_tests as t 
     JOIN t_user_answers as ua on ua.fk_test_id = t.pk_test_id 
     WHERE t.pk_test_id = testId and ua.fk_user_id = userId and is_correct(ua) = false; 
    $wrong_user_answers$ LANGUAGE sql; 

遺憾這並沒有改變錯誤。

最後我瞭解的@NamedStoredProcedureQuery註釋:

@NamedStoredProcedureQuery(name = "getWrongUserAnswers", 
          procedureName = "wrong_user_answers", parameters = { 
          @StoredProcedureParameter(name = "testId", type = Integer.class, mode = ParameterMode.IN), 
          @StoredProcedureParameter(name = "userId", type = Integer.class, mode = ParameterMode.IN) }, 
          resultClasses = UserAnswerBean.class) 
@Entity 
@Table(name = "t_user_answers") 
public class UserAnswerBean { 

隨着改變java代碼:

Query query = getEntityManager().createNamedStoredProcedureQuery("getWrongUserAnswers"); 
    query.setParameter("testId", testId); 
    query.setParameter("userId", userId); 
    List<UserAnswerBean> answers = query.getResultList(); 

這並沒有任何chnage錯誤!有人能幫我弄清楚我做錯了什麼嗎?

+0

如果Hibernate在refcursors中表現良好,我可能會感到非常驚訝,除非你做了本地查詢'FETCH'語句,而不是期望它將它們理解爲結果集。 – 2014-12-27 16:27:31

+0

看到我的第二次嘗試 - 沒有在那裏使用refcursor。順便說一句,我認爲我看到了一些地方,休眠消化refcursors沒有麻煩,可能玩智能和提取他們 – 2014-12-27 16:50:47

+0

它實際上是PgJDBC特殊情況下refcursor在某些情況下,通過正常的jdbc APIs將其視爲多個結果集。 – 2014-12-27 18:06:52

回答

1

不幸的是我能解決我的問題。

我想我可能在第二種方法中報告了錯誤的錯誤。我基本上沒有任何運氣與refcursors戰鬥,但使用LANGUAGE sql給了我想要的東西。這是存儲過程:

CREATE OR REPLACE FUNCTION wrong_user_answers(testId INTEGER, userId INTEGER) 
    RETURNS setof t_user_answers 
    AS $wrong_user_answers$ 
    SELECT ua.* 
     FROM t_tests as t 
     JOIN t_user_answers as ua on ua.fk_test_id = t.pk_test_id 
     WHERE t.pk_test_id = testId and ua.fk_user_id = userId and is_correct(ua) = false; 
    $wrong_user_answers$ LANGUAGE sql; 

由是,我已明確指定的返回類型之前,唯一的區別是setof t_user_answers。註釋和java代碼在問題中完全一樣,現在一切都適用於我。

PS:對於那些想知道我不得不更加努力次獲得當我有結果是沒有-DB實體一切順利,但最後我發現@SqlResultSetMapping批註與@ConstructorResultclasses subannotation解決問題(很難找到解決方案雖然)。

相關問題