Java postgresql jdbc中的结果集已关闭问题
我试图实现的是将每个员工的公钥存储在数据库中。我获取每个员工的employeeId并获取公钥,然后将employeeId和公钥同时存储到数据库中的另一个表中。只有第一次插入才会发生Java postgresql jdbc中的结果集已关闭问题,java,postgresql,jdbc,Java,Postgresql,Jdbc,我试图实现的是将每个员工的公钥存储在数据库中。我获取每个员工的employeeId并获取公钥,然后将employeeId和公钥同时存储到数据库中的另一个表中。只有第一次插入才会发生 package com.global.keyutil; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException
package com.global.keyutil;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Base64;
public class KeyUtil {
static private KeyPair generateKeyPair() {
KeyPair kp = null;
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
kp = kpg.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return kp;
}
static private String keyToString(PublicKey publicKey)
{
String b64PublicKey = null;
try
{
System.out.println("converting public key to string : ");
byte[] encodedPublicKey = publicKey.getEncoded();
b64PublicKey = Base64.getEncoder().encodeToString(encodedPublicKey);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
return b64PublicKey;
}
static private Connection getConnection()
{
Connection connection = null;
try {
Class.forName("org.postgresql.Driver");
connection = DriverManager.getConnection("jdbc:postgresql://127.0.0.1:5432/empris", "postgres","");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return connection;
}
static private void fetchAndStoreKeys(Connection connection)
{
Statement stmt = null;
try {
stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery( "select employeeid from employee where name<> 'Reception' and employeestatusid<>3 and employeestatusid<>6 order by name;" );
int i = 0;
while ( rs.next() ) {
System.out.println("Employee Id : ");
int id = rs.getInt("employeeid");
System.out.println(++i+" : "+id);
KeyPair kp = generateKeyPair();
PublicKey pub = kp.getPublic();
PrivateKey pvt = kp.getPrivate();
System.out.println("public key : "+pub);
System.out.println("private key : "+pvt+"\n");
String b64PublicKey = keyToString(pub);
System.out.println(b64PublicKey+"\n");
String query = "insert into keys(employeeid,publickey) values("+id+",'"+b64PublicKey+"')";
stmt.executeUpdate(query);
}
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args)
{
Connection connection = getConnection();
fetchAndStoreKeys(connection);
}
}
非常感谢您的帮助和提前感谢。来自:
如果存在打开的语句,则语句接口中的所有执行方法都会隐式关闭该语句的当前ResultSet对象
要解决您的问题,请尝试使用第二条语句执行insert。从循环内部:
while (rs.next()) {
// ...
String query = "insert into keys(employeeid,publickey) values (?, ?);"
PreparedStatement psInsert = connection.prepareStatement(query);
psInsert.setId(1, id);
psInsert.setString(2, b64PublicKey);
psInsert.executeUpdate();
}
请注意,我在这里使用的是一个准备好的语句,它允许我们绑定查询参数,而不必担心格式化、转义等问题。这是使用JDBC的首选方法。关于您的选择查询,如果您期望它始终是固定的,那么普通语句没有错,但是如果您认为在以后的某个时间点需要参数,请考虑使用准备好的语句。为什么要在try块的末尾关闭连接?否则,即使在插入完成后,连接也会被打开,这不是必需的,所以我在那里关闭了它。否则,请告诉我关闭连接的合适位置?您将在主方法中获取连接对象,因此您可以在
fetchAndStoreKeys
方法调用之后在主方法中关闭它,或者您可以在catch block
之后添加finally block
并关闭其中的连接。哦,是的,当然。忘了练习。谢谢你的建议。:)如果您使用的是Java7+,还有一个建议,请参考参考资料:是的,这就是问题所在,当我为插入部分使用单独的预处理语句时,问题就得到了解决。谢谢!文档参考是API文档:“如果存在打开的对象,语句
接口中的所有执行方法将隐式关闭该语句的当前ResultSet
对象。”@MarkRotteveel谢谢。我找错地方了。
while (rs.next()) {
// ...
String query = "insert into keys(employeeid,publickey) values (?, ?);"
PreparedStatement psInsert = connection.prepareStatement(query);
psInsert.setId(1, id);
psInsert.setString(2, b64PublicKey);
psInsert.executeUpdate();
}