My application uses a Mysql connection, which is obtained using this code:
public static void Connect(){
try
{
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "jdbc:mysql://" + host + ":" + port + "/"+ db;
ct = DriverManager.getConnection(url, user, pass);
st = ct.createStatement();
System.out.println("Csatlakozva....\n");
}
catch (InstantiationException e)
{
Main.textArea.setText("Error : Instantiation!");
//System.err.println("Error : Instantiation");
e.printStackTrace();
}
catch (IllegalAccessException e)
{
Main.textArea.setText("Error : Illegális Behatolás!");
//System.err.println("Error : Illegális Behatolás!");
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
Main.textArea.setText("Error : Class Nem Található!");
//System.err.println("Error : Class Nem Található!");
e.printStackTrace();
}
catch (SQLException e)
{
Main.textArea.setText("Error : Adatbázis Nem Található!");
//System.err.println("Error : Adatbázis Nem Található!");
e.printStackTrace();
}
}
If the MySQL database server is not running and therefore my app cannot open a connection, how do I make my app wait until a connection can be established?
In order to have your Connect method not return until a connection was actually obtained, you need to surround your existing try-block with a loop. Something like this:
public static void Connect() throws InterruptedException { // It isn't nice to block forever, so we will allow for interrupt
for (;;) {
try
{
Class.forName("com.mysql.jdbc.Driver").newInstance();
String url = "jdbc:mysql://" + host + ":" + port + "/"+ db;
ct = DriverManager.getConnection(url, user, pass);
st = ct.createStatement();
System.out.println("Csatlakozva....\n");
return; // Break out of loop because we got a connection - no exception was thrown
} ...
// One of the exceptions happened. We will continue to loop so
// we try to connect again until we are successful. We don't want
// to retry too fast, because painful experience has taught us that
// bad things can happen (full logs, 100% CPU, etc.).
Thread.sleep(1);
}
}
Exploring and understanding these sorts of low-level issues is a good exercise. However, I will just make a note here that (in my experience) most applications use a connection pool to manage database connections. Generally speaking, the connection pool would provide the functionality of blocking (usually for a limited time) until a connection can be obtained. In other words, the connection pool not only allows for reuse of previously-created connections, but also deal with connection retries when necessary.
I guess you have thread issue.
you can put the JDBC connection code to new thread
private class JDBCConnection extends Thread{
public void run(){
....
}
}
Related
I am developing a system which uses a database access object (DAO) to link between the program and database. All connections must be made through this class, using getConnection(). However, I have a reset option which overrides the database file in the user's file system with one inside the application itself (i.e. in its jar when deployed). This reset() feature causes an exception saying that the database is already in use.
java.nio.file.FileSystemException: C:\iMProve\improveDB.accdb: The process cannot access the file because it is being used by another process.
With research, this means that the connections have not been closed properly. However, I will show you the whole code for this DAO class if you can spot possibly where lies the problem.
public class DAO {
private static final String dbDir = "C://iMProve";
private static final String dbName = "improveDB.accdb";
private static final String dbUrl = "jdbc:ucanaccess://" + dbDir + "//"+ dbName;
private ObservableList<Connection> allConnections = FXCollections.observableArrayList();
public DAO() { //constructor - called when object is made
try {
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
} catch(ClassNotFoundException e) {
System.out.println("Cannot load ucanaccess driver");
e.printStackTrace();
}
File directory = new File(dbDir);
if(!directory.exists()) //create directory if not already
directory.mkdir();
File database = new File(dbDir + "//" + dbName);
if(!database.exists()) { //copy the database file into user's file system - if not already
try {
Files.copy(DAO.class.getResourceAsStream(dbName), database.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch(IOException ex) {ex.printStackTrace();}
}
}
public void reset() {
File database = new File(dbDir + "//" + dbName);
try {
Files.copy(DAO.class.getResourceAsStream(dbName), database.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
}
public Connection getConnection() { //create a connection to the database
Connection conn = null;
try {
conn = DriverManager.getConnection(dbUrl);
} catch (SQLException e) {
e.printStackTrace();
}
allConnections.add(conn);
return conn;
}
public void closeConnections() {
for(Connection conn: allConnections) {
if(conn!=null) {
try {
conn.close();
System.out.println("closed");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
The constructor simply copies the database from the application into the user's file system if not there already.
The getConnection() method connects to the database.
Calling reset() on its own produces that error, so by adding the connections to a static collection we can closing each and every connection, using closeConnections().
Note: These connections should already be closed anyways because we always a try-with-resources.
For example:
try (
Connection conn = dao.getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT Title FROM Theory WHERE Grade <= ?");
) {
And although we have two levels for closing connections
try-with-resources
closeConnections() method
They still are ineffective. When calling closeConnections(), we still get outputs of
closed
closed
even when connections have been used inside try-with-resources blocks.
And even with closeConnections(), we still get the same error:
java.nio.file.FileSystemException: C:\iMProve\improveDB.accdb: The process cannot access the file because it is being used by another process.
I deployed some apps in weblogic server. Few days ago, I traced logs and saw the error message:
2016-09-22 12:58:33,442 ERROR CommonService - ------- ERROR --------- java.sql.SQLException: Internal error: Cannot obtain XAConnection weblogic.common.resourcepool.ResourceDisabledException: Pool jdbc/*** is Suspended, cannot allocate resources to applications..
at weblogic.common.resourcepool.ResourcePoolImpl.reserveResourceInternal(ResourcePoolImpl.java:377)
at weblogic.common.resourcepool.ResourcePoolImpl.reserveResource(ResourcePoolImpl.java:342)
at weblogic.common.resourcepool.ResourcePoolImpl.reserveResource(ResourcePoolImpl.java:329)
at weblogic.jdbc.common.internal.ConnectionPool.reserve(ConnectionPool.java:417)
at weblogic.jdbc.common.internal.ConnectionPool.reserve(ConnectionPool.java:324)
at weblogic.jdbc.common.internal.ConnectionPoolManager.reserve(ConnectionPoolManager.java:94)
at weblogic.jdbc.common.internal.ConnectionPoolManager.reserve(ConnectionPoolManager.java:63)
at weblogic.jdbc.jta.DataSource.getXAConnectionFromPool(DataSource.java:1677)
at weblogic.jdbc.jta.DataSource.refreshXAConnAndEnlist(DataSource.java:1475)
at weblogic.jdbc.jta.DataSource.getConnection(DataSource.java:446)
at weblogic.jdbc.jta.DataSource.connect(DataSource.java:403)
at weblogic.jdbc.common.internal.RmiDataSource.getConnection(RmiDataSource.java:364)
at [my-package].ConnectionHandler.newDatabaseConnection(ConnectionHandler.java:37)
I think that having a app leeks connections and doesn't return them to the pool
At temporary solution, I have to extended the the connection pool.
I try to research which apps made this problem and see that some strange codes below:
public class ConnectionHandler
{
..
public ConnectionHandler()
{
logger.trace("ConnectionHandler() constructor called");
}
static Connection newDatabaseConnection() throws SQLException
{
Connection conn;
try {
Context initContext = new InitialContext();
DataSource dataSource = (DataSource) initContext.lookup(LOOKUP_URL);
conn = dataSource.getConnection();
conn.setAutoCommit(false);
} catch (NamingException e) {
logger.error("------- ERROR ---------", e);
throw new ProcessingError("Could not obtain database connection!");
}
return conn;
}
}
This app (SOAP service) will using the code below to query data once having requests:
if (connectionHandler == null) {
connectionHandler = new ConnectionHandler();
}
try {
conn = connectionHandler.newDatabaseConnection();
// Some callable statements here
conn.commit();
logger.info("------- OK ---------");
} catch (SQLException e) {
logger.error("------- ERROR ---------", e);
} catch (InstantiationException e) {
logger.error("------- ERROR ---------", e);
} catch (IllegalAccessException e) {
logger.error("------- ERROR ---------", e);
} catch (DossierServiceException e) {
logger.error("------- ERROR ---------", e);
} finally {
jdbc.close(conn);
}
My confusions which I do not understand yet:
Using the static connection in multi threads is ok?
Create new class (ConnectionHandler) for each request and then get static connection?
Just close the connection without closing the ResultSet, Callable statements?
Could you help me explanation for these ones or having some solutions else to prevent this problem?
The method is static not the result it's returning. static method means that it's not necessary to have an instance of the enclosing class to call it
Yes, that's a mistake, but, not such a big deal
Yes, it would be better first to close the result set, statement and the connection, but this should do the job
The problem with this code is that there's no conn.rollback() in catch blocks and there may be uncaught runtime exceptions that will not be rolled back
I have a project in which i connect to my Local Network DB. I Insert,Update and Select from DB, and DB type is SQL Server 2005.
I made a class named ConnectionHelper and everywhere i want to connect to DB, i make an Instance of it and then call its getConnection Method.
This class has a Constructor like this :
public ConnectionHelper() {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
setConnection(connection);
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver");
setIpAddress("X.X.X.X:1433");
setDb("XXX");
setUserName("XX");
setPassword("XXXX");
setConnectionURL("jdbc:jtds:sqlserver://" + getIpAddress() + ";"
+ "databaseName=" + getDb() + ";user=" + getUserName()
+ ";password=" + getPassword() + ";");
setConnection(DriverManager.getConnection(getConnectionURL()));
} catch (SQLException se) {
Log.e("ERRO", se.getMessage());
} catch (ClassNotFoundException e) {
Log.e("ERRO", e.getMessage());
} catch (Exception e) {
Log.e("ERRO", e.getMessage());
}
}
And this is getConnection Method :
public Connection getConnection() {
return connection;
}
And here is the sample of using this with Callable Statement( Call an Update Stored Procedure) :
ConnectionHelper connectionHelper = new ConnectionHelper();
CallableStatement callableStatement;
try {
callableStatement = connectionHelper.getConnection().prepareCall("{call MySP(?, ?, ?)}");
callableStatement.setInt(1, X);
callableStatement.setInt(2, X));
callableStatement.setInt(3, X);
callableStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
Well, it works good, But Android Devices connect to Local Network via WIFI, and sometimes they could not connect to DB due to Network Problems and then App close it by itself with unfortunately Error.
I want to handle if it could not connect to DB, retry again or display an Toast message to user and do not close the App.
How can i should handle the Exception?
I think you are already catching an exception - but SQLException - so you might find that the exception for connection issue is a Timeout or some other. In this case you need to change the part of your code into something like this:
ConnectionHelper connectionHelper = new ConnectionHelper();
CallableStatement callableStatement;
try {
callableStatement = connectionHelper.getConnection().prepareCall("{call MySP(?, ?, ?)}");
callableStatement.setInt(1, X);
callableStatement.setInt(2, X));
callableStatement.setInt(3, X);
callableStatement.executeUpdate();
} catch (SQLException e) {
//this is a specific SQL exception
e.printStackTrace();
}
catch (Exception e) {
//all other exceptions except the one above
//here you do your toast message
}
Catching the general Exception is good when you do not know all possible exceptions that could be thrown. Please give it a try and let us know if this helps.
Looks like you need an architecture that includes a "internal error" response to the nodes calling your services.
Must not catch the exception in the device, use web api's or webservices to comunicate with DBs.
Now, if your problem is error while processing because the local network on android is down plase look: How to check internet conection on android
I have connection provider class as bleow to return connection.
public class ConnectionProvider {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection ConnectDB() throws ClassNotFoundException, SQLException {
try (Connection connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/jspservlet_test","root", "root");
) {
return connection;
}
}
}
Here is main method to call connection provider.
public void Test() {
try {
Connection con = ConnectionProvider.ConnectDB();
PreparedStatement ps = con.prepareStatement("");
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
But "com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed." error are always show at below line of code.
PreparedStatement ps = con.prepareStatement("");
Because, according to Oracle documentation, If use try with resources java 7 features, resources are auto close after try block even it's errors occurred or not. So even I returned the connection it's already closed.
Let me know, my usage logic is wrong?
How can I return this connection inside try with resource?
I tried many time googling for solution but does not get convenience answers for me.
Let me know your suggestion and feedback please.
What you can't do...
With a try-with-resources as you have it after you return the connection you return(d) is close(d). You can't return the connection from inside the try with resources.
What you can do...
Pass the connection (inside your try-with-resources) to a method that takes a connection. You can also use a ConnectionPool, and get the Connection when you need it (to create and execute a query).
Let me know, my usage logic is wrong?
The usage of 'try-with-resources' logic is wrong in this context, because the intention of ConnectDB() is to return a connection instance which could be actually used by the caller to send a SQL statement, but instead, the connection instance is getting auto-closed, before it could be used by the caller, because of using 'try-with-resources' construct of Java.
Quick how-to on try-with-resource and JDBC
Your ConnectionProvider's ConnectDB already declares it is throwing SQLException - so no need to catch it in here: (You should consider replacing this code with connection pool maybe)
public class ConnectionProvider {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection ConnectDB() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/jspservlet_test","root", "root");
}
}
Instead use try-with-resource in your test-class to clean up your code and focus on errors your SQL code
might have:
public void Test() {
try (Connection con = ConnectionProvider.ConnectDB();
PreparedStatement ps = con.prepareStatement("SELECT 1")) {
//Prepare your Statement
ps.setInt(1, 1);
//And another try-with-resource for the result - note the closing brace
try(ResultSet rs = ps.executeQuery()) {
while(rs.next()) {
//Handle your Result
System.out.println(rs.getString(1));
}
} // This closes try-with-resource. Exception will be rethron to be caught in outer catch!
} catch (SQLException e) {
//SQL is Broken - but only ONE catch to catch them all
e.printStackTrace();
}
}
That way you gain
Better readability for your code (no calls to close surrounded by finally and if != null)
Centralized error handling if anything in your SQL code breaks (so you can focus on functional error of "statement didn't run")
Better code quality: No need to worry about Cursors, Statements, Connections not being propery closed.
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()