从 JDBC 调用的 PostgresQL 存储过程不起作用
PostgresQL stored procedure called from JDBC does not work
我有一个带有一些 table 的 postgresql 数据库和一个写入此 table 的存储过程。当我从 psql
调用此存储过程时,一切顺利:我看到我的记录插入到我的 table 中。
虽然,当我通过JDBC调用这个存储过程时,我得到了存储过程执行的日志,序列增加了,但是我的table没有更新。
这是我从全新的 postgresql 安装 (9.5.1) 执行的SQL:
Table创作:
CREATE SEQUENCE atable_id_seq;
CREATE TABLE IF NOT EXISTS "atable" (
"id" int NOT NULL DEFAULT NEXTVAL('atable_id_seq'),
"name" varchar(250) DEFAULT NULL,
PRIMARY KEY ("id")
);
创建存储过程:
CREATE OR REPLACE FUNCTION awrite(IN name character varying, OUT result character varying) AS
$$
BEGIN
INSERT INTO atable(name) VALUES (name)
RETURNING atable.id INTO awrite.result;
RAISE INFO 'Create awrite: %', name;
END
$$
LANGUAGE plpgsql;
从 psql
调用写入存储过程实际上会触发 postgres 中的日志并更新 table。
然后我写了一个java程序来调用同一个存储过程:
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName("org.postgresql.Driver");
hikariConfig.setJdbcUrl("jdbc:postgresql://127.0.0.1:5432/toto?charSet=UNICODE");
hikariConfig.setUsername("toto");
hikariConfig.setAutoCommit(false);
hikariConfig.setMinimumIdle(0);
hikariConfig.setMaximumPoolSize(2);
JdbcTemplate jdbcTemplate =
new JdbcTemplate(new HikariDataSource(hikariConfig));
SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate).withProcedureName("awrite");
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("name", "Foo");
call.addDeclaredParameter(new SqlOutParameter("result", Types.VARCHAR));
Map<String, Object> result = call.execute(params);
jdbcTemplate.execute("COMMIT;");
System.out.println("Result: ");
for (String s : result.keySet()) {
System.out.println(s + ": " + result.get(s));
}
我得到了一个 ID,执行很顺利。但是我的 table 不包含记录。
我不明白,也许有人可以帮助我?
我认为您的问题是您将 JDBC AutoCommit 标志设置为 false 但您没有使用 JDBC 事务。您需要 运行 您在 JDBC 事务中调用(最简单的方法是将您的代码放入方法中并使用 @Transactional
注释该方法或开始并提交 JDBC使用 TransactionTemplate
以编程方式进行交易)。像你这样调用 "COMMIT" 是行不通的。
我有一个带有一些 table 的 postgresql 数据库和一个写入此 table 的存储过程。当我从 psql
调用此存储过程时,一切顺利:我看到我的记录插入到我的 table 中。
虽然,当我通过JDBC调用这个存储过程时,我得到了存储过程执行的日志,序列增加了,但是我的table没有更新。
这是我从全新的 postgresql 安装 (9.5.1) 执行的SQL:
Table创作:
CREATE SEQUENCE atable_id_seq;
CREATE TABLE IF NOT EXISTS "atable" (
"id" int NOT NULL DEFAULT NEXTVAL('atable_id_seq'),
"name" varchar(250) DEFAULT NULL,
PRIMARY KEY ("id")
);
创建存储过程:
CREATE OR REPLACE FUNCTION awrite(IN name character varying, OUT result character varying) AS
$$
BEGIN
INSERT INTO atable(name) VALUES (name)
RETURNING atable.id INTO awrite.result;
RAISE INFO 'Create awrite: %', name;
END
$$
LANGUAGE plpgsql;
从 psql
调用写入存储过程实际上会触发 postgres 中的日志并更新 table。
然后我写了一个java程序来调用同一个存储过程:
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName("org.postgresql.Driver");
hikariConfig.setJdbcUrl("jdbc:postgresql://127.0.0.1:5432/toto?charSet=UNICODE");
hikariConfig.setUsername("toto");
hikariConfig.setAutoCommit(false);
hikariConfig.setMinimumIdle(0);
hikariConfig.setMaximumPoolSize(2);
JdbcTemplate jdbcTemplate =
new JdbcTemplate(new HikariDataSource(hikariConfig));
SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate).withProcedureName("awrite");
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("name", "Foo");
call.addDeclaredParameter(new SqlOutParameter("result", Types.VARCHAR));
Map<String, Object> result = call.execute(params);
jdbcTemplate.execute("COMMIT;");
System.out.println("Result: ");
for (String s : result.keySet()) {
System.out.println(s + ": " + result.get(s));
}
我得到了一个 ID,执行很顺利。但是我的 table 不包含记录。
我不明白,也许有人可以帮助我?
我认为您的问题是您将 JDBC AutoCommit 标志设置为 false 但您没有使用 JDBC 事务。您需要 运行 您在 JDBC 事务中调用(最简单的方法是将您的代码放入方法中并使用 @Transactional
注释该方法或开始并提交 JDBC使用 TransactionTemplate
以编程方式进行交易)。像你这样调用 "COMMIT" 是行不通的。