I am developing a java application that uses MySQL to write and read some data. After a while (very long time) my jdbc connection closes, i was reading on many forums and i still cannot make it last forever.
What i want to do is the next ting: After 5,6,24 hours (still don't know how many hours) i will close the connection and connect again. The problem is that if another thread tries to use that connection to write something it will fail on exception. So i want to do is the next thing if the jdbc connection is restarting all the threads that need to use the jdbc wait until the reconnect is finished. Also i don't want to block the thread if another thread uses that connection, only if is restarting. Also i am afraid of deadlocks :).
I was reading about java concurrency and how to manage it from many forums and still don't know what to use and how to use it.
Useful forums:
http://www.vogella.com/tutorials/JavaConcurrency/article.html
http://en.wikipedia.org/wiki/Java_concurrency
http://tutorials.jenkov.com/java-concurrency/index.html
Edit:
To make it more clear what i want to do
Java Database Class:
public class Database {
//Locks
final Object readLock = new Object();
final Object writeLock = new Object();
final Object readWriteLock = new Object();
boolean enableReadLock = false;
boolean enableWriteLock = false;
//Database parametars
String user; //DB username /корисник на базата
String password; //DB password /лозинка за базата
String dbname; //DB name / име на базата
String ip; //DB Server IP address / адреса на серверот каде е базата
Connection connection; //mysql connection /
public Database(String user, String password, String dbname, String ip) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
this.user = user;
this.password = password;
this.dbname = dbname;
this.ip = ip;
}
public Database(String user, String password, String dbname) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
this.user = user;
this.password = password;
this.dbname = dbname;
this.ip = "localhost";
}
public void setReadLock(boolean enable) {
enableReadLock = enable;
}
/**
* Enable or disable write lock
*
* @param enable true -> enable , false -> disable
*/
public void setWriteLock(boolean enable) {
enableWriteLock = enable;
}
/**
* Enable or disable read-write lock
*
* @param enable true -> enable , false -> disable
*/
public void setReadWriteLock(boolean enable) {
enableReadLock = enable;
enableWriteLock = enable;
}
public void reconnect() throws SQLException {
connection.close();
connection = DriverManager.getConnection("jdbc:mysql://" + ip + ":3306/" + dbname, user, password);
}
public void connect() throws SQLException {
connection = DriverManager.getConnection("jdbc:mysql://" + ip + ":3306/" + dbname, user, password);
}
public void disconnect() throws SQLException {
connection.close();
}
/**
* Test connection with mysql server
*
* @return (boolean) true -> OK, false -> NOK
*/
public boolean testConnection() {
String SQL = "SELECT 1";
try {
PreparedStatement statement = connection.prepareStatement(SQL);
ResultSet rs = statement.executeQuery();
while (rs.next()) {
}
} catch (SQLException ex) {
return false;
} catch (NullPointerException ex){
return false;
}
return true;
}
public ArrayList<HashMap<String, String>> executeSelect(String SQL) throws SQLException {
if (enableReadLock && enableWriteLock) { //Доколку има read-write lock
synchronized (readWriteLock) {
return select(SQL);
}
} else {
if (enableReadLock) { //Доколку има read-lock
synchronized (readLock) {
return select(SQL);
}
} else {
return select(SQL);
}
}
}
private ArrayList<HashMap<String, String>> select(String SQL) throws SQLException {
ArrayList<HashMap<String, String>> results = new ArrayList<>();
HashMap<String, String> row;
PreparedStatement statement = connection.prepareStatement(SQL);
ResultSet rs = statement.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int no_columns = rsmd.getColumnCount();
while (rs.next()) {
row = new HashMap<>();
for (int i = 1; i <= no_columns; i++) {
row.put(rsmd.getColumnName(i), rs.getString(i));
}
results.add(row);
}
statement.close();
rs.close();
return results;
}
public long executeInsert(String SQL) throws SQLException {
if (enableReadLock && enableWriteLock) {
synchronized (readWriteLock) {
return insert(SQL);
}
} else {
if (enableWriteLock) {
synchronized (writeLock) {
return insert(SQL);
}
} else {
return insert(SQL);
}
}
}
private long insert(String SQL) throws SQLException {
long ID = -1;
PreparedStatement statement = connection.prepareStatement(SQL, Statement.RETURN_GENERATED_KEYS);
statement.executeUpdate();
ResultSet rs = statement.getGeneratedKeys();
if (rs.next()) {
ID = rs.getLong(1);
}
statement.close();
return ID;
}
public int executeUpdate(String SQL) throws SQLException {
if (enableReadLock && enableWriteLock) {
synchronized (readWriteLock) {
return update(SQL);
}
} else {
if (enableWriteLock) {
synchronized (writeLock) {
return update(SQL);
}
} else {
return update(SQL);
}
}
}
private int update(String SQL) throws SQLException {
PreparedStatement statement = connection.prepareStatement(SQL);
int rez = statement.executeUpdate(SQL);
statement.close();
return rez;
}
public int executeDelete(String SQL) throws SQLException {
if (enableReadLock || enableWriteLock) {
synchronized (readWriteLock) {
synchronized (readLock) {
synchronized (writeLock) {
return delete(SQL);
}
}
}
} else {
return delete(SQL);
}
}
private int delete(String SQL) throws SQLException {
PreparedStatement statement = connection.prepareStatement(SQL);
int rez = statement.executeUpdate(SQL);
statement.close();
return rez;
}
}
In reconnect method i will need some lock or something that will make everyone who call select, update, insert or delete methods to wait (block) until the reconnect is finished.