我有一个我在PostgreSQL DB中创建的函数,我想用JPA 2.1的StoredProcedureQuery方法调用它。
这是我的PostgreSQL查询:
CREATE OR REPLACE FUNCTION get_values(date text) returns refcursor
AS $$
DECLARE tuples refcursor;
BEGIN OPEN tuples FOR
SELECT user, COUNT(*)
FROM my_table
WHERE date_ = date
GROUP BY user;
return tuples;
END;
$$
LANGUAGE plpgsql
这只是一个简单的查询来计算特定日期的用户。这只是一个演示查询,用于测试StoredProcedureQueries的工作方式。事实上,仅通过postgreSQL使用它就可以了。
现在,让我们尝试使用JPA 2.1和Javaland来调用它:
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("get_values");
storedProcedure.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter(1, Object.class, ParameterMode.REF_CURSOR);
storedProcedure.setParameter(2, "2015-02-01");
storedProcedure.execute();
当我这样做时,我得到了以下异常:
org.hibernate.HibernateException: PostgreSQL supports only one REF_CURSOR parameter, but multiple were registered
只声明了一个引用游标!实际上,如果我只是为WHERE date_ = date注册了单个REF_CURSOR参数和硬编码我的Postgresql函数的值,那么这个调用就可以了。
因此,似乎使用ref_cursor将任何其他参数添加到storedprocedurequery会破坏功能。单独,ref_cursor参数工作正常。
任何人都明白为什么会这样?为什么在PostgreSQL函数的StoredProcedureQuery中添加参数会破坏它?
何时起作用的例子:
CREATE OR REPLACE FUNCTION get_values(date text) returns refcursor
AS $$
DECLARE tuples refcursor;
BEGIN OPEN tuples FOR
SELECT user, COUNT(*)
FROM my_table
WHERE date_ = '2015-02-01'
GROUP BY user;
return tuples;
END;
$$
LANGUAGE plpgsql
并在javaland中:
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("get_values");
storedProcedure.registerStoredProcedureParameter(1, Object.class, ParameterMode.REF_CURSOR);
storedProcedure.execute();
答案 0 :(得分:5)
简答:将您的两次来电的顺序颠倒到 if a_before_b(listn[i]):
:
registerStoredProcedureParameter()
答案很长:我在Hibernate source code for Postgress callable statement support中进行了一些挖掘,发现每个storedProcedure.registerStoredProcedureParameter(1, Object.class, ParameterMode.REF_CURSOR);
storedProcedure.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
调用都会创建一个ParameterRegistrationImplementor
实例,该实例会被添加到列表中并传递。您将注意到此类存储参数的位置,该位置与其在列表中的位置无关。
稍后,此列表为analyzed,并假设registerStoredProcedureParameter()
参数将排在第一位,如果REF_CURSOR
参数不是第一个,,则抛出错误消息参数编号是。
不是一个非常聪明的做事方式(恕我直言),但至少解决方法很简单:如果你调换你的电话顺序,你应该没事。