I am getting the Exception with the signature No operations allowed after statement closed.
inside my Java code where I am trying to insert values into the database. The error signature says that my Statement object gets closed and I am trying to use it again in my code , but what I am struggling to understand is why is this happening as I am not closing any connections anywhere in my code.
Here is the Java code.
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;
}
Also I have observed that the error does not come when there is a single threaded execution , it comes up when multiple threads are trying to update the database simultaneously.
Create a Utility class for connection management to manage it at single point in whole application.
Don't load the DataSource
every time you need a new connection.
Sample code:
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;
}
}
Always close the connection and handle it in 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);
}
}
statement
is static, so it's shared among instances (and threads). One thread is probably trying to use that object after another one has closed it.
It is generally a bad idea to share database connections and statements between threads since JDBC does not require connections to be thread-safe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With