2014-12-27 80 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解决问题(很难找到解决方案虽然)。