I'm playing with this kind of database, and I've tried to close the HSQLDB connection after I used it, but it's still opened at the end.
Code:
//----This methods are in a specific connection class file
public static Connection conn = null;
public static Connection getConnection(){
try {
input = new FileInputStream("PathToMyPropertiesFile");
prop.load(input);
//The properties constants are correctly checked
Class.forName(prop.getProperty("DRIVER_HSQLDB"));
conn = DriverManager.getConnection(prop.getProperty("CONN_HSQLDB"));
}
catch(ClassNotFoundException | SQLException e) {
LOG.log(null,"Error: "+e);
}
catch (IOException ex) {
LOG.log(null,"FILE ERROR: "+ex);
}
finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
LOG.log(null,"CLOSE ERROR: "+e);
}
}
}
return conn;
}
public static boolean stopConn() {
try {
if(conn != null) {
conn.close();
System.err.println("\nCLOSE CONN\n"+conn);
return true;
}
}
catch (SQLException e) {
e.printStackTrace();
return false;
}
return false;
}
//========= the other class file with the methods to use the conneciton
public static boolean insertUser(String uName, String uEmail){
Connection con;
con = ConnectionDB.getConnection();
PreparedStatement ps = null;
try {
String consulta = "insert into USERS (\"NICK\",\"EMAIL\") VALUES(?,?);";
ps = con.prepareStatement(consulta);
System.err.println(ps);
ps.setString(1,uName);
ps.setString(2,uEmail);
System.err.println("\nASSIGNATION\n"+ps);
if(ps.executeUpdate() == 1) {
System.err.println("\nTRUE\n");
return true;
}
}
catch(SQLException e) {
e.printStackTrace();
}
finally {
try {
System.err.println("\nFINALLY\n"+ps);
if(ps != null) {
ps.close();
System.err.println("\nCLOSE PS\n"+ps);
}
if(con != null) {
con.close();
System.err.println("\nCLOSE CON\n"+con);
if(ConnectionDB.stopConn()) {
System.err.println("\nALL IS OK\n"+ConnectionDB.conn);
}
else {
System.err.println("\nMEEEEKKKK!!!\n"+ConnectionDB.conn);
}
}
}
}
return false;
}
The console give me this results, and I don't know why never the connection is closed because I tried to close it twice. If someone has an idea please tell me.
org.hsqldb.jdbc.JDBCPreparedStatement#4501280b[sql=[insert into USERS ("NICK","EMAIL") VALUES(?,?);], parameters=[[null], [null]]]
ASSIGNATION
org.hsqThis is my cldb.jdbc.JDBCPreparedStatement#4501280b[sql=[insert into USERS ("NICK","EMAIL") VALUES(?,?);], parameters=[[extra], [extra#mail.com]]]
TRUE
FINALLY
org.hsqldb.jdbc.JDBCPreparedStatement#4501280b[sql=[insert into USERS ("NICK","EMAIL") VALUES(?,?);], parameters=[[extra], [extra#mail.com]]]
CLOSE PS
org.hsqldb.jdbc.JDBCPreparedStatement#4501280b[closed]
CLOSE CON
org.hsqldb.jdbc.JDBCConnection#3e5b87f5
CLOSE CONN
org.hsqldb.jdbc.JDBCConnection#3e5b87f5
ALL IS OK
org.hsqldb.jdbc.JDBCConnection#3e5b87f5
Closing a JDBC connections does not close an in-process database. This allows you to open and close different connections during the runtime of your application.
You need to execute a JDBC Statement to shutdown the database. The SQL statement to execute is "SHUTDOWN".
It is possible to add a connection property "shutdown=true" to the JDBC connection URL to force a quick shutdown when the last connection to the in-process database is closed. But this is mainly useful for readonly or test databases. A full SHUTDOWN allows the database to open quickly the next time a connection is made.
See the Guide http://hsqldb.org/doc/2.0/guide/running-chapt.html#rgc_inprocess
Related
I'm using HikariCP 3.3.1 and PostgreSQL. But I've a problem with closing my connections, in Hikari config I set maximum pool size to 15 and minimum idle connection to 5, but after a few minutes of work with database I've found out connections don't closes, they stack more and more (almost 100 Idle connections right now).
My Connector class:
Connector.java
public class Connector implements IConnector {
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
static {
config.setDriverClassName(org.postgresql.Driver.class.getName());
config.setJdbcUrl("jdbc:postgresql://localhost:5432/vskDB");
config.setUsername("postgres");
config.setPassword("root");
config.setMinimumIdle(5);
config.setMaximumPoolSize(15);
config.setConnectionTimeout(20000);
config.setIdleTimeout(300000);
ds = new HikariDataSource(config);
}
public Connection getConnection() {
log.info("getConnection() invoked");
try {
return ds.getConnection();
} catch (SQLException e) {
log.error("Can't get connection from DataSource.");
log.error(e.getMessage());
System.out.println(e.getMessage());
}
return null;
}
Connector() {
}
}
And here's my DAO class (simplified):
UserDAO.java
public class UserDatabaseDAO implements UserDAO {
private Connector connector = new Connector();
private Connection dbConnection;
#Override
public void removeUser(Long id) {
try {
dbConnection = connector.getConnection();
if (dbConnection == null)
throw new ConnectException();
PreparedStatement preparedStatement = dbConnection.prepareStatement("DELETE FROM users WHERE user_id = ?");
preparedStatement.setLong(1, id);
preparedStatement.execute();
} catch (SQLException | ConnectException e) {
log.error("Can't remove user from database");
log.error(e.getMessage());
System.out.print(e.getMessage());
} finally {
try {
dbConnection.close();
} catch (SQLException e) {
log.error("Can't close connection");
log.error(e.getMessage());
System.out.print(e.getMessage());
}
}
}
}
Here I've found an issue with some facts about Hikari:
You must call close() on the connection instance that HikariCP gives you
Maybe my dbConnection.close() wont work because it's just a copy of Connection which Hikari gives me in getConnection() method.
You forgot to close also PreparedStatement
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources.
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
}
}
}
}
I create a Connection Connection con = ds.getConnection();(where ds is DataSource) in the open of the Reader and close it in the close() of the Reader.
But when i run a job with multiple partitions, in the middle of the job , i get Connection is closed error
Caused by: java.sql.SQLException: [jcc][t4][10335][10366][3.58.82] Invalid operation: Connection is closed. ERRORCODE=-4470, SQLSTATE=08003 DSRA0010E: SQL State = 08003, Error Code = -4,470
I assume this happens when one of the partition completes.
So my question is why does this happen? And how should connections be handled? Or does Java take care of closing the connections?
I am using Java Batch on WebSphere Liberty
UPDATE:
<jdbcDriver libraryRef="DB2JCC4Lib"/>
<properties.db2.jcc databaseName="" driverType="4" password="" portNumber="" queryDataSize="65535" serverName="" user=""/>
</dataSource>
public class Reader implements ItemReader {
private DataSource ds = null;
private Connection con = null;
public Reader() {
}
public void close() {
try {
con.close();
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* #see ItemReader#readItem()
*/
public Object readItem() {
String s="";
try {
if (rs.next()) {
for (int i = 1; i <= 10; i++) {
s+=rs.getString(i);
}
return s;
}
else {
return null;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
public Serializable checkpointInfo() {
}
public void open(Serializable checkpoint) {
if (ds == null) {
try {
ds = (DataSource) new InitialContext()
.lookup("java:comp/env/jdbc/dataSource");
} catch (Exception e) {
e.printStackTrace();
}
}
try {
con = ds.getConnection();
statement= con
.prepareCall("call abc.xyz(?)");
statement.setString("param", "xxx");
boolean result= statement.execute();
if (result) {
rs = statement.getResultSet();
if (rs == null) {
throw new NullPointerException();
}
} else {
throw new SQLException();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Complete error message
[ERROR ] J2CA0024E: Method rollback, within transaction branch ID {XidImpl: formatId(57415344), gtrid_length(36), bqual_length(40),
data(0000015645eff4470000000915937ff85f46c3ed056b19010aa5147e1183f8d3ae81c04c0000015645eff4470000000915937ff85f46c3ed056b19010aa5147e1183f8d3ae81c04c00000001)} of resource pool connectionManager[Pool], caught com.ibm.ws.exception.WsException: DSRA0080E: An exception was received by the Data Store Adapter. See original exception message: [jcc][t4][10335][10366][3.58.82] Invalid operation: Connection is closed. ERRORCODE=-4470, SQLSTATE=08003. with SQL State : 08003 SQL Code : -4470
I dont't know if JSR-352's Batch handles processing exactly the same way as Spring Batch does but...
In Spring Batch if you have a Reader that uses chunk processing what i think you could do to solve the problem is to put the openConnection() in the beforeRead() and the closeConnection() in the afterRead().
To do that you should implement a Listener. Check these out so you get an idea of what i'm talking about.
Spring Annotation Type BeforeRead
Interface ItemReadListener
Following is my Java code. In linux, it is working fine but in Windows I'm unable to insert data into the database on local disk. In NetBeans get it all right but .jar file not. JDBC driver see be good.
Connecting to database:
public static Connection connectToDb() {
try {
Connection connection = null;
DriverManager.registerDriver(new org.sqlite.JDBC());
//LINUX PATH
if (OSDetector.isLinux()) {
connection = DriverManager.getConnection("jdbc:sqlite:/home/" + userNameLinux + "/PDFMalwareDataAnalyser/DatabaseSQLite/database.db", NAME, PASSWORD);
//WINDOWS PATH
} else {
connection = DriverManager.getConnection("jdbc:sqlite:C:\\PDFMalwareDataAnalyser\\DatabaseSQLite\\database.db", NAME, PASSWORD);
}
connection.setAutoCommit(true);
if (connection != null) {
System.out.println("Otvorená.");
}
return connection;
} catch (SQLException e) {
System.err.println(e.getClass().getName() + e.getMessage());
// System.exit(0);
}
return null;
}
Insertion:
public void insertDataToDatabase(int idReport) throws SQLException {
connection = new SQLiteJDBC().connectToDb();
PreparedStatement insertCommunication = connection.prepareStatement("insert into table_communication values(?,?);");
insertCommunication.setString(2, communicationsFinal.toString());
try {
insertCommunication.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
insertCommunication.close();
connection.close();
System.out.println("1. --- Insert do tabuľky TABLE_COMMUNICATION OK ---");
}
Try this:
connection = DriverManager.getConnection("jdbc:sqlite:C:/PDFMalwareDataAnalyser/DatabaseSQLite/database.db")
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;
}