I've had more problems with my database in the past: It could not always get connection. The database runs on a website (webhosting), and I try to access it from my own PC. Here things go wrong, if I access it from localhost to localhost then it works okay.
Error that I get in Java: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
I got no clue why, I'm using similar structure as ever, namely the following:
public class SQL {
private final static String USERNAME = "";
private final static String PASSWORD = "";
private final static String URL = "jdbc:mysql://www.fvheeswijk.nl:3306/p28004_bf4";
private static Connection cachedConnection;
private static void createConnection() {
cachedConnection = null;
Properties connectionProperties = new Properties();
connectionProperties.put("user", USERNAME);
connectionProperties.put("password", PASSWORD);
try {
cachedConnection = (Connection) DriverManager.getConnection(URL, connectionProperties);
} catch (SQLException ex) {
Logger.getLogger(SQL.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static Connection getConnection() {
if (cachedConnection == null) {
createConnection();
}
return cachedConnection;
}
}
The data is blanked out of course.
I then tried to ping my website, all fine.
Later I tried to ping www.fvheeswijk.nl:3306, the database, but Windows cmd cannot find it. Then I tried visiting it via the browser (does this even make sense?), but I got some message along the lines of "packets received out of order". And I have already (way before) added my PC's (Router/Network's) host name to the allowed host list of the database.
Any clue or suggestions what is going wrong?
EDIT: Now I am getting this, might explain something... java.sql.SQLException: null, message from server: "Host '541DB0AA.cm-5-6c.dynamic.ziggo.nl' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'"
The main problem is that you are opening too much connections and probably never closing them or they are being closed by the application server (or wherever you run this application). This can be known from two facts in your post:
private static Connection cachedConnection. The database connection must not be cached manually, instead it should be retrieved only when needed, and closed after being used.
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed. This error is very explicit, you're trying to use a connection that is closed.
Also, you're naively opening connections manually, this is noted here:
cachedConnection = (Connection) DriverManager.getConnection(URL, connectionProperties);
To solve all these problems, you should move to a database connection pool. In short, the connection pool will open a bunch of physical database connections and keep them alive in sleeping status, and will wake up a connection on demand, then when closing the connection, instead of closing the physical connection, it will be back to the sleeping status, thus saving time for opening a new connection.
More info:
Is it a good idea to put jdbc connection code in servlet class?
How to properly keep a DB connection from a Connection Pool opened in JBoss
Java Mysql query database with connection
Should a database connection stay open all the time or only be opened when needed?
About your last edit, seems that you need to close some connections to your database. You should kill some of them and try to connect again using the database pool instead.
Related
I have a question about MySQL/JDBC connections in Java.
I wrote an application that successfully communicates with a database, but the issue that I recently found out was that my DB connection was dropping, and I need the application to have a connection to the DB at all times.
This is a small snipplet of the error I was getting:
com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 89,225,584 milliseconds ago. The last packet sent successfully to the server was 89,225,584 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1003)
This is also a snipplet of the constructor for my DBConnections class:
private final String url = "jdbc:mysql://localhost:3306/", database.....;
private Connection connection;
public DBConnector(){
try {
// Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url+database, username, password);
} catch (Exception ex) {
System.out.println("Error: " + ex);
}
}
In the errors section, I noticed it's telling me to add autoReconnect=true, I wondered; will my connection still stay up for longer if I structured the connection class like this:
connection = DriverManager.getConnection(url+database+"?autoReconnect=true", username, password);
If not, what else could I do to make sure my connection doesn't drop?
What I would suggest is to use a connection pool (Apache DBCP or HikariCP - the last one is currently having the best performance out of all solutions on the market) with configuration of testing connection before borrowing it from the pool. Depending on the library there should be an option like setTestOnBorrow(true).
In real applications you should always use connection pool instead of manually handling connections.
if i do close to connection database instead if i do close my resultSet ,what happend ?
I did write example to under.
For example.
Database.java
public class Database{
try{
Connection con;
PreparedStatement statement;
ResultSet resultSet;
public static void main{
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/database";
String _username="root";
String _password = "password";
Connection db = DriverManager.getConnection(url,_username,_password);
String sqlQuery = "select * from category";
statement = db.prepareStatement(sqlQuery);
resultSet = statement .executeQuery();
while(resuletSet.next()){
......
}
// i dont close connect.
resultSet.close();
//what happen then it? connection.close() , will it be automatically down ?
}catch(Exception e){
e.printStackTrace();
}
}
}
You're right to close your ResultSet carefully. Leaving those objects around after you finish with them is definitely a way to get memory leaks.
You should also close your Connection objects when you no longer need them. If your Java program terminates any Connection objects you still have open are closed, automatically. If no queries are in progress on those objects then the MySQL server closes the connection and cleans up when Java abandons the connection.
Java since version 7 has a way to manage this cleanly. You can do
try (Connection db = DriverManager.getConnection(url,_username,_password)){
//use the connection object
...
try (ResultSet result = stmt.ExecuteQuery(whatever)) {
// use the resultset
} catch (whatever) { whatever }
}
catch(whatever) { whatever }
This is is a nice way to avoid these leaks; the Connection and ResultSet objects get closed automatically at the end of the try / catch block just as if they were closed in a finally{} clause. It's called automatic resource block management.
Yes, close Connections when you're done with them. If you open a lot of Connection objects without closing them, two bad things happen:
Less bad: your Java program's RAM will leak.
More bad: your MySQL server's connection slots will fill up and it will start rejecting new connections. Client bugs which use up server resources are generally bad bugs.
Failing to close Connections can be pernicious, because typical programs don't use as many of them as ResultSets. So it takes longer to accumulate lots of unclosed connections, and you may not detect the problem while testing. Testers should log into the MySQL server directly and run the SHOW PROCESSLIST; command during system testing to see if unclosed Connections are accumulating.
Close your ResultSets and your Connections.
I have a bukkit plugin (minecraft) that requires a connection to the database.
Should a database connection stay open all the time, or be opened and closed when needed?
The database connection must be opened only when its needed and closed after doing all the necessary job with it. Code sample:
Prior to Java 7:
Connection con = null;
try {
con = ... //retrieve the database connection
//do your work...
} catch (SQLException e) {
//handle the exception
} finally {
try {
if (con != null) {
con.close();
}
} catch (SQLException shouldNotHandleMe) {
//...
}
}
Java 7:
try (Connection con = ...) {
} catch (SQLException e) {
}
//no need to call Connection#close since now Connection interface extends Autocloseable
But since manually opening a database connection is too expensive, it is highly recommended to use a database connection pool, represented in Java with DataSource interface. This will handle the physical database connections for you and when you close it (i.e. calling Connection#close), the physical database connection will just be in SLEEP mode and still be open.
Related Q/A:
Java Connection Pooling
Some tools to handle database connection pooling:
BoneCP
c3po
Apache Commons DBCP
HikariCP
Depends on what are your needs.
Creating a connection takes some time, so if you need to access database frequently it's better to keep the connection open. Also it's better to create a pool, so that many users can access database simultaneously(if it's needed).
If you need to use this connection only few times you may not keep it open, but you will have delay when you would like to access database. So i suggest you to make a timer that will keep connection open for some time(connection timeout).
You need to close your connections after each query executions.Sometimes you need to execute multiple queries at the same time because the queries are hanging from each other.Such as "first insert task then assign it to the employees".At this time execute your queries on the same transaction and commit it, if some errors occur then rollback.By default autocommit is disabled in JDBC. Example
Use connection pooling.If you are developing a webapplication then use App Server connection pooling.App server will use the same pooling for each of your applications so you can control the connection count from the one point.Highly recommend the Apache Tomcat Connection pooling.Example
As an additional info:
Connection, Statement and ResultSet.
1.If you close connection you don't need close statement or resultset.Both of them will be closed automatically
2.If you close Statement it will close ResultSet also
3.if you use try-with-resources like this:
try (Connection con = ...) {
} catch (SQLException e) {
}
it will close the connection automatically.Because try-with-resources require autoclosable objects and Connection is autocloseable.You can see the details about try-with-resources here
Actually, it's all matter on how you write your application! It's an art, but sadly everyone takes a tutorial for a good practice like Microsoft's tutorials.
If you know what you are coding, then you keep your connection open for the lifetime of the application. It's simple, not because you have to go at work in the morning that everyday we have to build a special route just for you! You take that single route or 2 or 4 like everyone does! You judge for the traffics and you build 2, 4 or 6 routes as needed. If there is traffic with these 4 or 6 routes, you wait!
Happy coding.
The Connection should be opened only when required. If it is open before the actual need, it reduces one active connection from the connection pool..so it ultimately effects the users of the application.
So,it is always a better practice to open connection only when required and closing it after completion of process.
Always try puttting you connection close logic inside the finally block that will ensure that your connection will be closed,even if any exception occurs in the application
finally
{
connection.close()
}
I'm using JBoss AS 7.1 as a server and I have my DataSource configured with pooling. I'm quite new to this so please excuse any rookie mistakes... after all I'm here to learn.
When a client logs-in it gets a connection to the database and I need to keep that connection(from the pool) open until the user logs-out or the HttpSession expires. This is an absolute requirement coming from our DB Admin. who says that he needs the DB session variables. I am using a servlet for all this.
Playing with the possibilities I have encountered 2 major problems:
As far as I see JBoss automatically closes unused connections => my opened connection returns to the pool. So this might not be the right path.
If I try to store/recall the Connection object like this:
private Hashtable<String, Connection> connections = new Hashtable<String, Connection>();
try {
String strDSName1 = "java:/OracleDSJNDI";
ctx = new InitialContext();
ds1 = (javax.sql.DataSource) ctx.lookup(strDSName1);
System.out.println("Got 1'st ds.");
} catch (Exception e) {
System.out.println("ERROR getting 1'st DS : " + e);
}
connection = ds1.getConnection();
connections.put(session.getId(), connection);
conn = (Connection) connections.get(sessionID);
it throws this exception:
java.sql.SQLException: Connection is not associated with a managed
connection.org.jboss.jca.adapters.jdbc.jdk6.WrappedConnectionJDK6#dee1f37
My question is: How do I properly keep my connection opened?
Thanks
How do I properly keep my connection opened?
You must not do that, let the connection pool handle this.
Behind the scenes, the connection pool will keep a bunch of database connections to the database engine (MySQL, Oracle, SQL Server... depends how you configure it) in SLEEPING state. When you execute this code:
//avoiding all the particular exceptions just for code simplicity purposes...
//in real world applications, you must handle each of these exceptions
public Connection getConnection() throws Exception {
ctx = new InitialContext();
ds1 = (javax.sql.DataSource) ctx.lookup(strDSName1);
return ds1.getConnection();
}
You're asking to the connection pool to retrieve one of these connections available. The connection pool will give you a database connection (if available) and let you use it as long as you want. Then you use it wherever you want/need and close it:
public void foo() throws Exception {
Connection connection = getConnection();
//do what you want/need...
//in the end, you close the connection
//this is A MUST!
connection.close();
}
When executing connection.close() from a connection retrieved by the connection pool, you're not closing the physical database connection but notifying the connection pool this specific database connection must return to the SLEEPING state.
Some advices from the explanation:
You must not try to keep the connection alive, that's connection pool's job.
You must not try to store the connections in any cache-like structure, that's connection pool's job.
You must retrieve a java.sql.Connection in the shortest scope you will need it. Once you have used it, close it.
Your DBA is basically requiring you to avoid connection pooling by making the database connection equivalent to the user's session.
So one option is to not use the connection pool, and instead roll your own functionality that opens/closes the database connection around the user's session. That seems complicated and unusual though.
Another option is to examine the DBA's requirement. The DBA may have to adapt to the idea that he'll need to track state in a different way, e.g. by using a key related to the session to store the state he needs in a table, instead of storing state in the connection layer.
Generally speaking storing state in some component's session handling is adding indirect complexity, because you start having to care about how the component handles expiry and uniqueness, as you're finding here where the HTTP session state handles this differently from the database session.
I am developing a web application using JSP & Servlet (IDE: Eclipse, Database: Oracle10).
I have developed java class which returns a static connection, and that connection will be used by my entire web application.
public class DBConnection
{
private static Connection con = null;
static Connection getConnection(String str)
{
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection("MyValuesHere");
System.out.println("New instance of Connection is created for: "+str);
}
catch(ClassNotFoundException cnfe)
{
System.out.println("Error loading class!");
cnfe.printStackTrace();
}
catch(SQLException sqle)
{
System.out.println("Error connecting to the database!");
sqle.printStackTrace();
}
return con;
}//getConnection()
}//class
Above class is working fine. Then I have another 4 java classes for
Inserting
Updating
Deleting
Selecting
data from database using the above connection. So in those 4 classes I am getting connection which is created in my DBConnection class, and those four classes are also working fine. This four classes are used in my all Servlet's.
To get Connection in those 4 classes I am writing following line:
private static Connection con = DBConnection.getConnection("UpdateQuery.java");
But problem is that I want to share the same connection in all four classes, but connection is created separately in those 4 classes. So how should I share the same connection in those four classes? is there better way of doing this? and if I use this approach will there be any issues in web application because of sharing the connection for whole application?
You are (implicitly) trying to solve a non-trivial task.
Such things are normally done by the container - taking connections from a pool, then returning them back, reconnection etc...
If you use a fully functional applications server you'd better configure and use data sources.
If your server doesn't support data sources, do not mess up with saving connection into a private field. What for example happenes when your connection is lost? Your private variable will have a non-working connection. Do you have any recovery mechanism?
Your code will be much more robust if you get it in the beginning of the business operation and then close it.
Or try to find a professionally written library that supports connection pools - it will do pretty much the same as a classic container in handling a connection pool.
Or write it yourself, but it will be a separate task with many questions.
Looks like you wanted to turn Connection into a singleton but then forgot to check whether it's been instantiated already. In getConnection you could check if con is not null in the first place and return that instance right away. Only if con is still null, proceed with initialization.
You should save the created connection instance into a private static field in DBConnection, and when getConnection is called, you check if the field is null, then create the connection, then return it:
if (connection == null) {
connection = createConnection();
}
return connection;
where connection is a private static Connection connection field of DBConnection class.
However I strongly suggest to not use this approach as sharing a connection between concurrent threads will cause serious problems. I suggest to use connection pooling