为什么 H2 别名重复插入的行?
Why does H2 alias duplicate inserted rows?
我创建了以下 H2 别名:
CREATE ALIAS INSERT_CHANGE_RECORD AS '
java.sql.ResultSet insertChangeRecord(final java.sql.Connection conn) throws java.sql.SQLException
{
String sql = "insert into `change_records` (`made_when`, `made_by`) values (CURRENT_TIMESTAMP(9), ''admin'');";
java.sql.PreparedStatement ps = conn.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS);
ps.executeUpdate();
java.sql.ResultSet results = ps.getGeneratedKeys() ;
return results;
}
';
奇怪的是,当我使用 call INSERT_CHANGE_RECORD();
调用别名(一次)时,在 table 中创建了 3 条相同的记录,而不是一条。
当我改为使用以下别名定义时(不同之处在于我实际上是从结果集中检索生成的 ID),仅插入 1 行。
CREATE ALIAS IF NOT EXISTS INSERT_CHANGE_RECORD AS '
Long insertChangeRecord(final java.sql.Connection conn) throws java.sql.SQLException
{
String sql = "insert into `change_records` (`made_when`, `made_by`) values (CURRENT_TIMESTAMP(9), ''admin'');";
java.sql.PreparedStatement ps = conn.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS);
ps.executeUpdate();
java.sql.ResultSet results = ps.getGeneratedKeys();
results.next();
return results.getLong(1);
}
';
这是 H2 中的错误,还是对此行为有任何合理的解释?我正在使用 H2 2.1.210.
这是我插入的table的DDL。
CREATE TABLE IF NOT EXISTS `change_records` (
`id` BIGINT NOT NULL AUTO_INCREMENT CONSTRAINT `change_records_id_pk` PRIMARY KEY,
`made_when` TIMESTAMP (9) WITH TIME ZONE NOT NULL,
`made_by` VARCHAR NOT NULL
);
函数别名 returning a ResultSet
被多次调用。您需要检查已通过的连接 URL。如果它等于 jdbc:columnlist:connection
,则需要 return 具有正确配置的列的空 ResultSet
,您可以使用 org.h2.tools.SimpleResultSet
或其他一些实现。这些调用是在查询实际执行之前的编译或重新编译期间执行的。
String url = conn.getMetaData().getURL();
if (url.equals("jdbc:columnlist:connection")) {
SimpleResultSet rs = new SimpleResultSet();
// With some connection options "id" should be used instead
rs.addColumn("ID", Types.BIGINT, 19, 0);
return rs;
}
// main code
此结果集的列名称和数据类型必须与您的函数通常 returns 完全相同。注意列名,`id`
通常表示 "ID"
,但是如果在您的应用程序使用的 JDBC URL 中指定了 ;DATABASE_TO_LOWER=TRUE
或 ;DATABASE_TO_UPPER=FALSE
,这意味着 "id"
。您的函数在此执行期间不应修改任何数据,它只会询问其元数据。
如果URL不同,那是在执行查询或其他命令期间真正的函数调用,您需要执行您的代码。
我创建了以下 H2 别名:
CREATE ALIAS INSERT_CHANGE_RECORD AS '
java.sql.ResultSet insertChangeRecord(final java.sql.Connection conn) throws java.sql.SQLException
{
String sql = "insert into `change_records` (`made_when`, `made_by`) values (CURRENT_TIMESTAMP(9), ''admin'');";
java.sql.PreparedStatement ps = conn.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS);
ps.executeUpdate();
java.sql.ResultSet results = ps.getGeneratedKeys() ;
return results;
}
';
奇怪的是,当我使用 call INSERT_CHANGE_RECORD();
调用别名(一次)时,在 table 中创建了 3 条相同的记录,而不是一条。
当我改为使用以下别名定义时(不同之处在于我实际上是从结果集中检索生成的 ID),仅插入 1 行。
CREATE ALIAS IF NOT EXISTS INSERT_CHANGE_RECORD AS '
Long insertChangeRecord(final java.sql.Connection conn) throws java.sql.SQLException
{
String sql = "insert into `change_records` (`made_when`, `made_by`) values (CURRENT_TIMESTAMP(9), ''admin'');";
java.sql.PreparedStatement ps = conn.prepareStatement(sql, java.sql.Statement.RETURN_GENERATED_KEYS);
ps.executeUpdate();
java.sql.ResultSet results = ps.getGeneratedKeys();
results.next();
return results.getLong(1);
}
';
这是 H2 中的错误,还是对此行为有任何合理的解释?我正在使用 H2 2.1.210.
这是我插入的table的DDL。
CREATE TABLE IF NOT EXISTS `change_records` (
`id` BIGINT NOT NULL AUTO_INCREMENT CONSTRAINT `change_records_id_pk` PRIMARY KEY,
`made_when` TIMESTAMP (9) WITH TIME ZONE NOT NULL,
`made_by` VARCHAR NOT NULL
);
函数别名 returning a ResultSet
被多次调用。您需要检查已通过的连接 URL。如果它等于 jdbc:columnlist:connection
,则需要 return 具有正确配置的列的空 ResultSet
,您可以使用 org.h2.tools.SimpleResultSet
或其他一些实现。这些调用是在查询实际执行之前的编译或重新编译期间执行的。
String url = conn.getMetaData().getURL();
if (url.equals("jdbc:columnlist:connection")) {
SimpleResultSet rs = new SimpleResultSet();
// With some connection options "id" should be used instead
rs.addColumn("ID", Types.BIGINT, 19, 0);
return rs;
}
// main code
此结果集的列名称和数据类型必须与您的函数通常 returns 完全相同。注意列名,`id`
通常表示 "ID"
,但是如果在您的应用程序使用的 JDBC URL 中指定了 ;DATABASE_TO_LOWER=TRUE
或 ;DATABASE_TO_UPPER=FALSE
,这意味着 "id"
。您的函数在此执行期间不应修改任何数据,它只会询问其元数据。
如果URL不同,那是在执行查询或其他命令期间真正的函数调用,您需要执行您的代码。