JAVA JDBC reusing connections - java

I have a Java program in which I am doing some JDBC for select queries. Will it be advisable to call testDataBase() each time which inturns calls DBConnection() each time or I should reuse one connection for all the queries. Thanks in advance.
private void testDataBase(String query){
Connection con = DBConnection();
Statement st = null;
ResultSet rs = null;
try {
st = con.createStatement();
rs = st.executeQuery(query);
boolean flag = true;
while (rs.next()) {
String resultString = "";
for(int i = 1; i <=rs.getMetaData().getColumnCount();i++){
resultString=resultString+" "+ rs.getString(i);
}
System.out.println(resultString);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
private Connection DBConnection() {
final String method_name = "DBConnection";
Connection conn = null;
try{
Class.forName(driver).newInstance();
conn = java.sql.DriverManager.getConnection(url,userName,password);
}catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
} catch (SQLException e) {
System.out.println(e.getMessage());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return conn;
}

Opening a DB connection is an expensive operation in terms of perfofmance. You should use a ConnectionPool for sharing connections among different requests.

Connections are not thread safe, so sharing them across requests is not a good idea.
A better idea is to pool connections and keep their scope as narrow as possible: check the connection out of the pool, use it, close it in transaction scope.

Database connections are long-running and should be re-used, unless you have a very low query rate.

Getting a database connection is quite an expensive operation, so it is advisable to re-use a connection if possible. Consider also using connection pooling, which will maintain a number of connections for you, so you can just grab one from the pool when needed. The method shown above might not need to change, it depends on the DBConnection() method you call.

I completely agree with #Amir Kost, in terms of performances, opening a DB connection in one of the slowest operation that you can do, and if you have restrictive real time constraints it could be a big issue.
I do not know if you are using a framework or not, but a good practice is to publish a bean which wrap a pool of connection and every time that you need to interact directly with the db, you get the current open connection (which usually corresponds to a so called "session").
I suggest to you, (even if you are not using any framework) to reproduce this technicality.

If you want only one instance of Connection, you can make use of the Singleton pattern, you can consider :
public class Connector {
private static final String URL = "jdbc:mysql://localhost/";
private static final String LOGIN = "root";
private static final String PASSWORD = "azerty";
private static final String DBNAME = "videotheque";
private static Connector connector;
private static Connection connection;
private Connector() {
}
public synchronized static Connector getInstance() {
if (connector == null) {
connector = new Connector();
}
return connector;
}
public static Connection getConnection() {
if (connection == null) {
Connection c = null;
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
c = DriverManager.getConnection(URL + DBNAME, LOGIN, PASSWORD);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return c;
}
return connection;
}
}
And then, you can call : Connector.getInstance().getConnection()

Related

HSQLDB never closes DB connection

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

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
}
}
}
}

Java - Tomcat GC won't free up.. always cause crash, can't find any memory leak

I have few issues with my tomcat application.
I'm using a linux server with 1024M memory.
I deploy my app on the tomcat, and everything working great.
Recently i notice that the 'Tenured Gen' heap memory not free up when it should...
It reach 99% and then crash tomcat..
I check my application with VisualVM, and the same result.
it fill up the memory and the 'Old Gen' never free up.
This is when the application run few minutes with no request:
IMG: Everything looks normal
And when I start to send requests with 200 Thread on a loop
this what happened:
IMG: all memories are full
So then I check data on the MAT, and this is my result:
IMG: look like a memory leak
IMG: Problem with the sql jdbc?
IMG: Can't understand what is wrong
this is my ConnectionPool class:
public class ConnectionPool {
private static ConnectionPool singleton = null;
private ArrayList<Connection> freeConnections;
private ArrayList<Connection> allConnections;
private int MAX_CONNECTIONS = 1;
private final String shema = "Topic";
private final String url = "jdbc:mysql://localhost:3306/"+shema+"? autoReconnect=true&useSSL=false";
private final String username = "root";
private final String password = "password";
public static ConnectionPool getInstance(){
if (singleton == null)
{
synchronized (ConnectionPool.class) {
if (singleton == null){
System.out.println("ConnectionPool get instance");
try {
singleton = new ConnectionPool();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //this will invoke the constructor
}
}
}
return singleton;
}
private ConnectionPool() throws Exception {
freeConnections = new ArrayList<Connection>();
allConnections = new ArrayList<Connection>();
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < MAX_CONNECTIONS; i++) {
try {
addNewConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void addNewConnection() throws SQLException {
try {
Connection conn = DriverManager.getConnection(url, username, password);
freeConnections.add(conn);
allConnections.add(conn);
} catch (SQLException e) {
throw e;
}
}
public Connection getConnection()
{
while (true) {
synchronized (freeConnections) {
if (freeConnections.size() != 0) { // free connection is available
Connection conn = freeConnections.get(0);
freeConnections.remove(0);
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
try {
freeConnections.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void returnConnection(Connection conn)
{
if (null == conn) { // ignore invalid value
return;
}
if (!allConnections.contains(conn)) {
return;
}
synchronized (freeConnections) {
if (freeConnections.contains(conn)) {
return;
}
freeConnections.add(conn);
freeConnections.notifyAll();
return;
}
}
public void closeAllconnections()
{
for (Connection conn : allConnections) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
System.out.println("ConnectionPool all connection closed");
deregisterDriver();
}
public void deregisterDriver() {
try {
java.sql.Driver driver = DriverManager.getDriver(url);
DriverManager.deregisterDriver(driver);
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("ConnectionPool deregister driver");
}
}
Please help me to understand what is wrong and explain me.
1.Why the GC won't free up or why he can't do his job?
2.Is something wrong with my ConnectionPool Class?
3.why tomcat not saying anything about OutOfMemoryException in my logs(just crashing)?
See the connection details, apparently you have 10 connections and each retains cca 66 MB if the heap summing up to 660 MB required RAM.
I don't know what data you select, however when returning a connection you may want to close all resultsets and statements (why are you creating your own pool? dbcp, c3p0 or commons-pool ain't good enough? for learning?) and seems it may be not enough. I really don't know what the pool implementations do to release all resources properly.
And seems it is not so straightforward to share open connections between multiple threads Java MySQL JDBC Memory Leak so I would suggest to use a working pool solution (dbcp)

rollback mysql transcations from multiplate methods GWT

I'm trying to figure out how to rollback commits from multiple methods. I want to do something like the following (editing for brevity)
public void testMultipleMethodRollback() throws DatabaseException {
Connection conn = connect();
fakeMethodRollback1();
fakeMethodRollback2();
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
and currently all my methods are formatted like this
public void fakeMethodRollback1() throws DatabaseException {
Connection con = connect();
PreparedStatement ps = null;
ResultSet rs = null;
// insert some queries
try {
String query = "some query";
ps = conn.prepareStatement(query);
ps.executeUpdate(query);
query = "some query";
ps = conn.prepareStatement(query);
ps.executeUpdate(query);
con.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new DatabaseException(e);
} finally {
close(rs, ps, conn);
}
}
because I want to be able to use the other methods independently, how can I do a rollback where if one method fails, the others will roll back? I fear I have my whole class setup wrong or at least wrong enough that this can't be accomplished without major work. I can't change the methods to return a connection, because half of my methods are get methods, which are already returning other data. Any ideas?

combination of Oracle database and in-memory database in java program

I am going to enhance the performance of my program. For this purpose I am going to implement some parts of my program to be done in memory instead of database. I dont know which one is better in this regards, in-memory database or normal java data structure.For in-memory database I considered Tentimes from oracle and H2. So another question would be which solution is better for around 100 million records of data on single machine for single user? Also another question would be is the old way of database connection works fine in this way? Here is the connection that I used for oracle, What is the appropriate Driver for this purpose.
public static Connection getConnection(){
//If instance has not been created yet, create it
if(DatabaseManager.connection == null){
initConnection();
}
return DatabaseManager.connection;
}
//Gets JDBC connection instance
private static void initConnection(){
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String connectionUrl = "jdbc:oracle:thin:#localhost:1521:" + dbName;
DatabaseManager.connection =
DriverManager.getConnection(connectionUrl,"****","****");
}
catch (ClassNotFoundException e){
System.out.println("Oracle driver is not loaded!");
System.exit(0);
}
catch (SQLException e){
System.out.println(e.getMessage());
System.exit(0);
}
catch (Exception e){
}
}
public static ResultSet executeQuery(String SQL) throws SQLException
{
CachedRowSetImpl crs = new CachedRowSetImpl();
ResultSet rset = null ;
Statement st = null;
try {
st = DatabaseManager.getConnection().createStatement();
rset = st.executeQuery(SQL);
crs.populate(rset);
}
catch (SQLException e) {
System.out.println(e.getMessage());
System.exit(0);
}finally{
rset.close();
st.close();
}
return crs;
}
public static void executeUpdate(String SQL)
{
try {
Statement st = DatabaseManager.getConnection().createStatement();
st.executeUpdate(SQL);
// st.close();
}
catch (SQLException e) {
System.out.println(e.getMessage());
System.exit(0);
}
}
Regards.

Categories