问题描述
您好,感谢您的阅读。 我正在尝试检索新插入的数据的ID,但是我总是得到一个空的ResultSet。
Connection con = main.getCon();
String sqlCommand = "Insert Into Relations(name,explanation) values(?,?)";
PreparedStatement state =
con.prepareStatement(sqlCommand,Statement.RETURN_GENERATED_KEYS);
state.setString(1,name.getText());
state.setString(2,explanation.getText());
int affectedRows = state.executeUpdate();
assert (affectedRows>0);
ResultSet rs = state.getGeneratedKeys();
assert rs.next();
int instertedID= rs.getInt("ID");
不确定这是怎么回事。在线检查了不同的样本,但无法找出我的错误。
我也用Statement尝试过,但也没有运气。
要点1:代码运行流畅,我的数据已插入数据库中。
第2点:在这种情况下,有在线示例,您可以在此处查看:
https://www.baeldung.com/jdbc-returning-generated-keys
我刚刚意识到ResultSet不为空,我在使用调试器时遇到问题,这就是为什么我认为它为空。 正如Mark Rotteveel在评论中提到的那样,问题出在“断言”声明上。
解决方法
问题是您使用了assert rs.next()
。 Java中的断言旨在检查不变性(例如,在测试期间),但是当您正常运行Java时,assert
语句不会执行,只有在使用-ea
命令行选项显式启用此语句时,才会执行它们。 / p>
因此,不会调用rs.next()
,因此当您调用rs.getInt(1)
时,结果集仍位于第一行之前。而是使用if (rs.next()) { ... }
。
这取决于数据库引擎。一些提示:
JDBC是低级的,不适合用于编程
这是一个复杂的API。使用更轻松的方法:JDBI或JOOQ。他们可能对插入有一些抽象,可以为您解决这些问题。
某些数据库引擎要求您列出列名
尝试:
con.prepareStatement(sqlCommand,new String[] {"UNID"});
某些数据库引擎只会将生成的值作为直接结果集返回
请勿致电.executeUpdate()
;而是调用.executeQuery()
返回一个ResultSet
;检查那个。
还有其他事情
如果上述方法无济于事,请发布您正在使用的确切表结构和数据库引擎。
您的代码已损坏
除非您安全地这样做并且不能安全地这样做,否则您不能创建资源对象(一旦必须被关闭)。使用try-with-resources:
String sql = "INSERT INTO relations(name,explanation) VALUES (?,?)";
try (Connection con = main.getCon();
PreparedStatement ps = con.prepareStatement(sql,new String[] {"unid"})) {
state.setString(1,name.getText());
state.setString(2,explanation.getText());
try (ResultSet rs = state.executeQuery()) {
if (!rs.next()) throw new SQLException("insert didn't return autogen?");
System.out.println(rs.getInt(1));
}
}
ResultSet,Statement,PreparedStatement和Connections都是资源(必须关闭!)-如果要将这些内容之一存储在字段中,则可以这样做,但前提是包含该字段的类本身是资源:必须具有close()方法,必须实现AutoClosable
,然后您才能使用上述try-with-resources制作此类的实例。
不遵守这些规则意味着您的应用程序似乎可以运行,但是在运行时会泄漏资源,因此,如果让它运行足够长时间,它将开始崩溃。另外,随着越来越多的连接一直处于打开状态并永久卡住,您的数据库引擎将陷入停顿。
,将最后一行代码更改为此,因为您使用的DBMS可能不支持按列名获取值,因此请传递该列的索引:
int instertedID = rs.getInt(1);
,
String sqlCommand = "Insert Into Relations (name,explanation) values(?,?)";
PreparedStatement state = con.prepareStatement(sqlCommand,Statement.RETURN_GENERATED_KEYS);
state.setString(1,name.getText());
state.setString(2,explanation.getText());
state.executeUpdate();
ResultSet resultSet = state.getGeneratedKeys();
if(resultSet.next()) {
System.out.println(resultSet.getInt(1)); //Indicate the corresponding column index value.
}