What is the accurate syntax for SQLite JDBC Connections? - java

This is may look like a repeated question but, it is not. I have tried looking for an answer for this over 48 hours with no result.
Firstly, is closing PreparedStatment & ResultSet necessary in SQLite JDBC Connection? because I am unable to do so.
try {
Class.forName(database.getJDBC_DRIVER());
cnn = DriverManager.getConnection(database.getDB_URL());
p = cnn.prepareStatement(query);
rs = p.executeQuery();
p.close();
cnn.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
System.out.println(p.isClosed());
if (cnn != null) cnn.close();
System.out.println(p.isClosed());
} catch (SQLException e) {
e.printStackTrace();
}
}
As you can see, I closed PreparedStatement inside the try block. However, When I'm checking the state of same outside the try block, the result is always false. (which means it isn't closed).
Besides, if I have below code in the finally block, it throws an error stating the connection is closed. I am super confused on what to do. Should I just leave it as it is. Wouldn't my code have some leakage?
} finally {
try {
if (p != null) p.close(); *// It errors out here...*
if (cnn != null) cnn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
Below is the stack trace -
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (Connection is closed)
at org.sqlite.core.DB.newSQLException(DB.java:890)
at org.sqlite.core.CoreStatement.internalClose(CoreStatement.java:109)
at org.sqlite.jdbc3.JDBC3Statement.close(JDBC3Statement.java:35)
at tg.cat.DropDown.getData(DropDown.java:28)
at tg.loginscreen.LoginScreenLayout.<init>(LoginScreenLayout.java:22)
at tg.cat.CatMain.getScene(CatMain.java:27)
at tg.cat.CatMain.start(CatMain.java:18)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159(Unknown Source)
at com.sun.javafx.application.LauncherImpl$$Lambda$53/855499929.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$45/186276003.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$170(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/1635925971.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/237061348.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source)
at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

The finally block is executed regardless of whether an exception was thrown or not. So you don't need to use it to close the connection again, but to use it as the only place you close the connection. Second, note that closing a connection will not reset the variable to null:
try {
Class.forName(database.getJDBC_DRIVER());
cnn = DriverManager.getConnection(database.getDB_URL());
p = cnn.prepareStatement(query);
rs = p.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
if (p != null) {
p.close();
}
if (cnn != null) {
cnn.close();
}
} catch (SQLException e) {
System.err.println("Can't close an object, not much I can do");
}
}

Mureinik is right, but even better to use the try-with-resources feature, so that you don't even have to worry about closing anything (manually) in the first place.
try (Connection cnn = DriverManager.getConnection(database.getDB_URL());
PreparedStatement p = cnn.prepareStatement(query)) {
// prepare your statement
try (ResultSet rs = p.executeQuery()) {
// process result set
}
} catch (SQLException e) {
throw new RuntimeException("Unexpected SQLException", e);
}

Related

Fortify: fails to release a database resource

I am trying to see the vulnerability of my code with fortify. The report said that I have an issue which said "the function sometimes fails to release a database resource allocated by". Here is the code and in which line the issue pointed. I've tried to close the connection in the finally block but it not solve the issue. How to fix this?
private AnotherService anotherService;
private void create() {
Connection conn = null;
try {
conn = getCon(); // With fortify, there's an issue which said "the function sometimes fails to release a database resource allocated by", and it refers to this line
conn.setAutoCommit(false);
anotherService.myFunction(conn);
// the conn.commit() is inside anotherService, because I have to make one connection
// rest of code
} catch (Exception e) {
e.printStackTrace;
if (null != conn) {
conn.rollback();
}
} finally {
if (null != conn) {
conn.close();
}
}
}
private static Connection getCon() {
Connection connection = null;
try {
Class.forName("org.postgresql.Driver");
connection = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/dbname",
"username",
"password");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
Addition:
If I use try-with-resource (like this try (Connection conn = getCon()), to automatically close things, how I could call conn.rollback() in the catch block if any exception occured? Since the conn variable declared inside the try-with-resources.
Well, I solve my problem, the close method should call inside try-catch in the finally block, as mentioned in this link.
In case the link broken, here is the code that I use to solve my problem:
Statement stmt = null;
ResultSet rs = null;
Connection conn = getConnection();
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(sqlQuery);
processResults(rs);
} catch (SQLException e) {
// Forward to handler
} finally {
try {
if (rs != null) {rs.close();}
} catch (SQLException e) {
// Forward to handler
} finally {
try {
if (stmt != null) {stmt.close();}
} catch (SQLException e) {
// Forward to handler
} finally {
try {
if (conn != null) {conn.close();}
} catch (SQLException e) {
// Forward to handler
}
}
}
}

SonarLint is still showing blocker errors even though we have handled the statement, Connection closes in finally block

SonarLint is showing below errors:
'Use try-with-resources or close this "Statement" in a "finally" clause.'
'Use try-with-resources or close this "Connection" in a "finally" clause.'
blocker errors even though we have closed the Statement stmt, Connection con in finally block.
Please find the sample code.
public String getProductNumber() throws BusinessDelegateException {
String productNo = null;
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
String query = //some query
try {
DataSource ds = getDataSource();
con = ds.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery(query);
productNo =.......
....................
}catch (Exception e) {
String errorMsg = "Error occured in getProductNumber()";
throw new BusinessDelegateException(errorMsg, e);
}finally{
try {
if(rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return productNo;
}
We were able to fix the issue by modifying the finally block in below manner. But still it seems like repetition of catch blocks. Any other way we can fix this?
finally{
try {
if(rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (stmt != null)
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con != null)
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
Without try-with-resources you can only improve the code by using methods for re-usability, call main method:
closeResources(rs, stmt, con);
Which will call each for each resource a different method for example Statement:
public void closeResource(Statement stmt) {
if (stmt != null) {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
BTW, you better use logger instead of e.printStackTrace()
For complete solution, you can check extensive example which add resources in array and close them in a loop:
for (Closeable resource : resources) {
try {
resource.close();
Use Try-with-resources. This is the best option.

simple mysql/jdbc code causing a memory leak?

I'm trying to analyze a heap dump to find a memory leak for the first time. I'm opening up the heap dump using MAT and right away it's pretty clear it's one object? that is taking up almost the entire heap and it's a sql class com.mysql.cj.jdbc.ConnectionImpl.
Since sql is really used in only one part of my code it basically has to be something with this small bit of code here...
static Connection getDBconn() {
Connection conn = null;
while (conn == null) {
try {
conn = DriverManager.getConnection(serverURL, user, pass);
} catch (SQLException e) {
Logger.logError(e);
}
}
return conn;
}
static void update(String sql) {
while (currConn == null)
currConn = getDBconn();
boolean error = false;
do {
try {
currConn.createStatement().executeUpdate(sql);
} catch (SQLException e) {
try {
currConn.close();
} catch (SQLException e1) {
Logger.logError(e1);
}
currConn = getDBconn();
Logger.logError(e);
error = true;
}
} while (error);
}
static ResultSet query(String sql) {
while (currConn == null)
currConn = getDBconn();
ResultSet rs = null;
while (rs == null) {
try {
rs = currConn.createStatement().executeQuery(sql);
} catch (SQLException e) {
try {
currConn.close();
} catch (SQLException e1) {
Logger.logError(e1);
}
currConn = getDBconn();
Logger.logError(e);
}
}
return rs;
}
What this code is supposed to do is basically wrap query/update statements inside some methods to ensure that each command is always carried out eventually, even when an error comes up. My program will be running for long amounts of time with many requests, and i want to ensure it deals with all possible problems automatically without interrupting the program.
What i have written will work for about an hour or so and then i'll get a out of memory error even when i have my heap set to like 8gb which is obviously overkill. I should also note i'm not getting any sql errors so it's not even getting into the catch blocks. Clearly there is some sort of leak with this code but i'm having trouble figuring out what it could be. Any advice would be appreciated and i can provide more information on the heap dump if needed.
You are getting connection when you don't need it twice
try {
currConn.close();
} catch (SQLException e1) {
Logger.logError(e1);
}
--> currConn = getDBconn();
Logger.logError(e);
Just remove currConn = getDBconn() after currConn.close(); and you won't have connection leak.
Better yet, close connection on finally even if no error occurred:
try {
rs = currConn.createStatement().executeQuery(sql);
} catch (SQLException e) {
Logger.logError(e);
finally{
try {
currConn.close();
} catch (SQLException e1) {
Logger.logError(e1);
}
}
Also create a method to prevent code duplication and different implementation of closing connection.

NullPointerException at while(rs.next())

I have a simple program that executes a query agains a Sybase ASE DB using jconnect6 .
the program throws a NullPointerException after iterating for 603 records of the ResultSet
public ResultSet exec()
{
ResultSet rs = null;
try {
stmt= connection.createStatement();
rs = stmt.executeQuery(query);
} catch (SQLException ex) {
ex.printStackTrace();
}
try {
connection.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
return rs;
}
public void Test()
{
ResultSet rs= exec();
if(rs!=null)
{
int i=0;
try {
while(rs!=null && rs.next()) { // NullPointerException here
System.out.println(i++);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
The output prints the value for 'i' till it reaches 603 while the collected records are more than 1000 and below is the error
May 13, 2014 11:43:43 AM appcomponents.OutageTest Test
SEVERE: null
java.lang.NullPointerException
at com.sybase.jdbc3.timedio.RawDbio.reallyRead(Unknown Source)
at com.sybase.jdbc3.timedio.Dbio.doRead(Unknown Source)
at com.sybase.jdbc3.timedio.InStreamMgr.a(Unknown Source)
at com.sybase.jdbc3.timedio.InStreamMgr.doRead(Unknown Source)
at com.sybase.jdbc3.tds.TdsProtocolContext.getChunk(Unknown Source)
at com.sybase.jdbc3.tds.PduInputFormatter.a(Unknown Source)
at com.sybase.jdbc3.tds.PduInputFormatter.read(Unknown Source)
at com.sybase.jdbc3.tds.TdsInputStream.read(Unknown Source)
at com.sybase.jdbc3.tds.TdsInputStream.readInt(Unknown Source)
at com.sybase.jdbc3.tds.TdsDataObject.readINTN(Unknown Source)
at com.sybase.jdbc3.tds.TdsInt.beginRead(Unknown Source)
at com.sybase.jdbc3.tds.TdsDataObject.doRead(Unknown Source)
at com.sybase.jdbc3.tds.TdsInt.getLong(Unknown Source)
at com.sybase.jdbc3.tds.CachedTdsInt.<init>(Unknown Source)
at com.sybase.jdbc3.tds.TdsInt.createCachedCopy(Unknown Source)
at com.sybase.jdbc3.tds.TdsResultSet.cacheCurrentRow(Unknown Source)
at com.sybase.jdbc3.tds.TdsResultSet.next(Unknown Source)
at com.sybase.jdbc3.jdbc.SybResultSet.next(Unknown Source)
at appcomponents.OutageTest.Test(OutageTest.java:143)
You should not close your connection until you have finished reading from the ResultSet.
public ResultSet exec() {
ResultSet rs = null;
try {
stmt = connection.createStatement();
rs = stmt.executeQuery(query);
} catch (SQLException ex) {
ex.printStackTrace();
}
return rs;
}
public void Test() {
ResultSet rs = exec();
try {
if (rs != null) {
int i = 0;
try {
while (rs != null && rs.next()) { // NullPointerException here
System.out.println(i++);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
// ** Close your connection AFTER you've finished with the ResultSet
connection.close();
}
}
I have found that after executing the query at
rs = stmt.executeQuery(query);
I close the connection and this is the code that runs after the modification:
public ResultSet exec()
{
ResultSet rs = null;
try {
stmt= connection.createStatement();
rs = stmt.executeQuery(query);
} catch (SQLException ex) {
ex.printStackTrace();
}
// try {
// connection.close(); //this is what was wrong with the code
// } catch (SQLException ex) {
// ex.printStackTrace();
// }
return rs;
}
You can try to change :
while(rs!=null && rs.next())
To
while(rs.next()) ?

Is that the best way to release SQLite connection in Java?

I need a good way to close SQLIte connections in Java. After a few suggestion by other users I decided to add to my code a finally block to be sure that closing operation are always executed.
public static boolean executeQuery(String query)
{
Connection conn = null;
Statement stmt = null;
try
{
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection(Global.dbPath);
stmt = conn.createStatement();
stmt.execute(query);
return true;
}
catch(ClassNotFoundException e)
{
System.out.println(e);
return false;
}
catch(SQLException e)
{
System.out.println(e);
return false;
}
finally
{
try
{
stmt.close();
conn.close();
return true;
}
catch (SQLException ex)
{
System.out.println ("Errore closing connections");
return false;
}
}
}
I'm not sure that this is the best solution.
How can I optimize this for readability?
A few comments; nutshells:
Separate the SQL exceptions from the reflection exception.
Are your SQL exceptions recoverable? If not, throw an app-specific RuntimeException.
Wrap up the connection and statement close exceptions in a utility method, yours or a 3rd party's.
Don't short-change exception handling; dump the stack trace.
This leads to the following:
public static boolean executeQuery(String query) {
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
throw new DbException("Could not find JDBC driver", e);
}
Connection conn = null;
Statement stmt = null;
try {
conn = DriverManager.getConnection(Global.dbPath);
stmt = conn.createStatement();
stmt.execute(query);
return true;
} catch(SQLException e) {
throw new DbException("Exception during statement execution", e);
} finally {
DbUtils.closeQuietly(conn);
DbUtils.closeQuietly(stmt);
}
}
(I'm using Apache Commons' DbUtils for its closeQuietly, it checks for null (yours didn't). Your own version might throw an app-specific exception as I do here with DbException. This wraps up all your DB-related exceptions into a single exception class, which may or may not be what you need.
If you want to make sure a command is executed you have to put it alone into a try catch block:
try {
stmt.close();
}
catch (Exception ex) {
}
try {
conn.close();
}
catch (Exception ex) {
System.out.println ("Error closing connections");
return false;
}

Categories