Java 使用PostgreSQL函数游标错误的Spring批处理ItemReader
我需要让Spring批处理ItemReader使用PostgreSQL函数作为数据源,但我没有成功(PostgreSQL数据库在Greenplum设备中)。我创建了一个ItemReader调用PostgreSQL函数的示例,该函数返回一个游标,但ItemReader无法声明游标不存在。以下是我的设置的所有组件: -数据库表和数据:Java 使用PostgreSQL函数游标错误的Spring批处理ItemReader,java,spring,postgresql,cursor,spring-batch,Java,Spring,Postgresql,Cursor,Spring Batch,我需要让Spring批处理ItemReader使用PostgreSQL函数作为数据源,但我没有成功(PostgreSQL数据库在Greenplum设备中)。我创建了一个ItemReader调用PostgreSQL函数的示例,该函数返回一个游标,但ItemReader无法声明游标不存在。以下是我的设置的所有组件: -数据库表和数据: CREATE TABLE test_user ( test_user_sys_id numeric NOT NULL, ssn character v
CREATE TABLE test_user
(
test_user_sys_id numeric NOT NULL,
ssn character varying(9) NOT NULL,
create_user_id character varying(30) NOT NULL,
create_ts timestamp(6) without time zone NOT NULL DEFAULT now()
)
WITH (
OIDS=FALSE
)
DISTRIBUTED BY (ssn);
INSERT INTO test_user (test_user_sys_id, ssn, create_user_id) VALUES (1,'111111111','DataAdmin');
INSERT INTO test_user (test_user_sys_id, ssn, create_user_id) VALUES (2,'222222222','DataAdmin');
INSERT INTO test_user (test_user_sys_id, ssn, create_user_id) VALUES (3,'333333333','DataAdmin');
-数据库功能:
CREATE or REPLACE FUNCTION get_user_func_no_arg(
p_id_min NUMERIC -- Minimum ID value
)
RETURNS REFCURSOR
AS
$BODY$
DECLARE
resultCursor REFCURSOR := 'resultCursor';
BEGIN
OPEN resultCursor FOR
SELECT test_user_sys_id, ssn
FROM test_user
WHERE test_user_sys_id > p_id_min;
RETURN resultCursor;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
package dao.setter;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.springframework.jdbc.core.PreparedStatementSetter;
// Spring Batch PreparedStatementSetter to set parameters for stored procedures
public class TestUserPreparedStatementSetter implements PreparedStatementSetter {
private int minId;
// Setters
public void setMinId(int minId) {
this.minId = minId;
}
// Set the parameters for the stored procedure
public void setValues(PreparedStatement ps) throws SQLException {
CallableStatement cs = (CallableStatement) ps;
cs.setInt(1, this.minId);
cs.registerOutParameter(2, java.sql.Types.OTHER);
}
}
-localLaunchContext.xml(特定于环境的信息):
-TestUserPreparedStatementSetter.java(将输入参数设置为PostgreSQL函数):
-TestUserRowMapper.java(将ItemReader光标行映射到TestUser数据对象):
当我运行此操作时,会出现以下错误:
Caused by: org.postgresql.util.PSQLException: ERROR: cursor "resultCursor" does not exist
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:405)
at org.postgresql.jdbc2.AbstractJdbc2Connection.execSQLQuery(AbstractJdbc2Connection.java:363)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.internalGetObject(AbstractJdbc2ResultSet.java:207)
at org.postgresql.jdbc3.AbstractJdbc3ResultSet.internalGetObject(AbstractJdbc3ResultSet.java:36)
at org.postgresql.jdbc4.AbstractJdbc4ResultSet.internalGetObject(AbstractJdbc4ResultSet.java:300)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getObject(AbstractJdbc2ResultSet.java:2704)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:456)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:412)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:205)
... 29 more
我反复尝试将REFCURSOR指定为函数的输出参数以及其他许多事情,但没有成功。这是使用JDK1.7、PostgreSQL JDBC驱动程序JAR PostgreSQL-9.3-1102.jdbc4和PostgreSQL 8.2.15(在Greenplum 4.2.8.1构建2下)实现的
欢迎提出任何建议。提前感谢。经过大量调查,我找到了修复方法-将数据源更改为支持禁用自动提交的数据源:
<!-- Define the PostgreSQL source -->
<bean id="postgresql_dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="THE URL"/>
<property name="username" value="THE USER"/>
<property name="password" value="THE PASSWORD"/>
<property name="defaultAutoCommit" value="false"/>
</bean>
package dao.setter;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.springframework.jdbc.core.PreparedStatementSetter;
// Spring Batch PreparedStatementSetter to set parameters for stored procedures
public class TestUserPreparedStatementSetter implements PreparedStatementSetter {
private int minId;
// Setters
public void setMinId(int minId) {
this.minId = minId;
}
// Set the parameters for the stored procedure
public void setValues(PreparedStatement ps) throws SQLException {
CallableStatement cs = (CallableStatement) ps;
cs.setInt(1, this.minId);
cs.registerOutParameter(2, java.sql.Types.OTHER);
}
}
package dao.mapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import domain.TestUser;
//Spring RowMapper to support stored procedure results
public class TestUserRowMapper implements RowMapper<TestUser>{
// Map the results to the DAO
public TestUser mapRow(ResultSet resultSet, int rowNum) throws SQLException
{
TestUser resultData = new TestUser();
resultData.setId(resultSet.getInt(1));
resultData.setSsn(resultSet.getString(2));
return resultData;
}
}
java -classpath ".;lib\*;bin" org.springframework.batch.core.launch.support.CommandLineJobRunner localLaunchContext.xml TestUserJob minId=1
Caused by: org.postgresql.util.PSQLException: ERROR: cursor "resultCursor" does not exist
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:405)
at org.postgresql.jdbc2.AbstractJdbc2Connection.execSQLQuery(AbstractJdbc2Connection.java:363)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.internalGetObject(AbstractJdbc2ResultSet.java:207)
at org.postgresql.jdbc3.AbstractJdbc3ResultSet.internalGetObject(AbstractJdbc3ResultSet.java:36)
at org.postgresql.jdbc4.AbstractJdbc4ResultSet.internalGetObject(AbstractJdbc4ResultSet.java:300)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getObject(AbstractJdbc2ResultSet.java:2704)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:456)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:412)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:205)
... 29 more
<!-- Define the PostgreSQL source -->
<bean id="postgresql_dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="THE URL"/>
<property name="username" value="THE USER"/>
<property name="password" value="THE PASSWORD"/>
<property name="defaultAutoCommit" value="false"/>
</bean>