【发布时间】:2015-02-24 11:14:41
【问题描述】:
我正在开发一个 Java 应用程序,最近一位同事建议我,如果我使用存储过程来满足我的某些需求,我的解决方案会变得更加简洁。我开始阅读它们,它们看起来很有希望,但现在我很难让 Hibernate 将这种存储过程返回的结果映射到 java bean。
这是我想要达到的程序:
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 部分:
UserAnswerBean 中的附加注解(@NamedNativeQuery):
@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();
当代码在上面最后一行尝试执行时,收到以下错误:
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,而不是立即返回 select 的结果,所以我将存储过程更改为:
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();
这也没有改变错误!有人可以帮我弄清楚我做错了什么吗?
【问题讨论】:
-
如果 Hibernate 能够很好地使用 refcursors,我会感到非常惊讶,除非您执行本机查询
FETCH语句而不是期望它将它们理解为结果集。 -
查看我的第二次尝试 - 那里没有使用 refcursor。顺便说一句,我想我在某个地方看到了 hibernate 可以毫无问题地消化 refcursors,可能玩得很聪明并获取它们
-
它实际上是 PgJDBC 在某些上下文中特殊情况下的 refcursor,通过普通的 jdbc API 将其视为多个结果集。
标签: java sql hibernate postgresql stored-procedures