我在Java代码中使用签名No operations allowed after statement closed.
获取Exception,我试图在数据库中插入值。错误签名说我的Statement对象被关闭了,我试图在我的代码中再次使用它,但我正在努力理解的是为什么会发生这种情况,因为我没有关闭代码中的任何连接。
这是Java代码。
public class DataBaseAccessUtils {
private static String jdbcUrl =
AppConfig.findMap("BXRequestTracker").get("jdbcUrl").toString();
private static Connection connection = null;
private static Statement statement = null;
public static void insertHostname(String hostname, String rid, String fleet, String locale)
{
locale.toUpperCase();
String sql = "UPDATE " + locale + "REQUESTTRACKER SET " + fleet
+ "='" + hostname + "' WHERE RID='" + rid + "'";
try {
statement.execute(sql);
}
catch (SQLException e) {
e.printStackTrace();
}
}
public static Statement connectToDatabase() {
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(DataBaseAccessUtils.jdbcUrl);
statement = connection.createStatement();
}
catch (Exception e) {
e.printStackTrace();
}
return statement;
}
此外,我发现当存在单个线程执行时,错误不会发生,当多个线程同时尝试更新数据库时,它会出现。
答案 0 :(得分:3)
为连接管理创建一个Utility类,以便在整个应用程序中的单点管理它。
每次需要新连接时都不要加载DataSource
。
示例代码:
public class ConnectionUtil {
private DataSource dataSource;
private static ConnectionUtil instance = new ConnectionUtil();
private ConnectionUtil() {
try {
Context initContext = new InitialContext();
dataSource = (DataSource) initContext.lookup("JNDI_LOOKUP_NAME");
} catch (NamingException e) {
e.printStackTrace();
}
}
public static ConnectionUtil getInstance() {
return instance;
}
public Connection getConnection() throws SQLException {
Connection connection = dataSource.getConnection();
return connection;
}
public void close(Connection connection) throws SQLException {
if (connection != null && !connection.isClosed()) {
connection.close();
}
connection = null;
}
}
始终关闭连接并在try-catch-finally
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = ConnectionUtil.getInstance().getConnection();
...
} finally {
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
ConnectionUtil.getInstance().close(conn);
}
}
答案 1 :(得分:2)
statement
是静态的,因此它在实例(和线程)之间共享。一个线程可能在另一个线程关闭之后尝试使用该对象。
在线程之间共享数据库连接和语句通常是个坏主意,因为JDBC不要求连接是线程安全的。
答案 2 :(得分:0)
可能是因为你正在使用两个不同的预备语句
方法和你close(pst.close())
语句在一个方法中仍然尝试在另一个方法中使用相同的语句。
要解决此问题,请在您遇到此错误的代码块中获取新连接,然后使用statement。
如果你对两种不同的方法使用相同的语句,如果你没有在任何方法中关闭语句,那么你可能会收到这个错误:
参数索引超出范围(2>参数个数,即1)。
因为同样的陈述。因此,尝试为代码块获取单独的连接和语句,然后关闭连接和语句。