I am trying to setup a boneCP connection and I am getting the following error message:
Exception in thread "main" java.lang.ClassCastException: com.jolbox.bonecp.StatementHandle cannot be cast to com.mysql.jdbc.Statement
The connection seems to work fine but I get stopped out at the query.
Here is my code:
BoneCP connectionPool = null;
Connection connection = null;
try {
// load the database driver (make sure this is in your classpath!)
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
return;
}
try {
// setup the connection pool
BoneCPConfig config = new BoneCPConfig();
config.setJdbcUrl("jdbc:mysql://192.126.0.0:3306/"); // jdbc url specific to your database, eg jdbc:mysql://127.0.0.1/yourdb
config.setUsername("root");
config.setPassword("");
config.setMinConnectionsPerPartition(5);
config.setMaxConnectionsPerPartition(10);
config.setPartitionCount(1);
connectionPool = new BoneCP(config); // setup the connection pool
connection = connectionPool.getConnection(); // fetch a connection
if (connection != null){
System.out.println("Connection successful!");
Statement stmt = (Statement) connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1 FROM table"); // do something with the connection.
while(rs.next()){
System.out.println(rs.getString(1)); // should print out "1"'
}
}
connectionPool.shutdown(); // shutdown connection pool.
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
This is quite simple: If you use BoneCP, you do not have direct access to the objects of the underlying driver. This applies to connection pools in general, because they usually object proxies to handle resource management (eg close statements, resultsets etc when the connection is returned to the pool). This especially applies to statements as connection pools can (and usually do) also provide statement caching.
Specifically for BoneCP you should be able to get to the wrapped statement using StatementHandle.getInternalStatement() (although I am not 100% sure about that).
Although the big question is: why do you need to cast to com.mysql.jdbc.Statement, isn't the java.sql.Statement interface sufficient for you?
Related
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 query regarding fetching jdbc connection from pool in sub method.Following are two method i came across suggest me which one best to avoid connection leakage and tell if any other solution.
Method 1:
getConnection is method which return Connection.
void testMain(){
Connection conn = getConnection();
subMethod(conn)
conn.close();
}
void subMethod(connection conn){
// use jdbc connection
return;
}
Method2:
void testMain(){
Connection conn = getConnection();
subMethod()
conn.close();
}
void subMethod(){
Connection conn = getConnection();
conn.close();
return;
}
The place where you need a Connection should get the connection.
The way you ensure that no resources are "leaked" is by using java 7's try-with-resource syntax:
public String fetchSomeData() {
try (Connection conn = getConnection()) { // This line, with this syntax, will ensure that it is automatically closed in an invisible "finally" block
// Do what you need to do with the data, return it or something else
} catch (SQLException e) {
// No need to do clean up here, log the exception or do whatever you want.
}
}
You can use try-with-resource syntax on any objects that implement AutoCloseable interface. That includes Connection, Statement, and Resultset among others.
If you need to do a transaction you might want to initialize the Connection in a method, and then pass that Connection to different other methods that adds to the transaction, and then commit it. If that's the case, you can do:
public String fetchSomeDataInTransactionStyle() {
try (Connection conn = getConnection()) { // This line, with this syntax, will ensure that it is automatically closed in an invisible "finally" block
conn.setAutocommit(false);
addSomethingToTransaction(conn);
addSomethingMore(conn);
conn.commit();
} catch (SQLException e) {
// No need to do clean up here, log the exception or do whatever you want.
}
}
I have a java library to query mysql database, the return the ResultSet to another Java function. Because of the mysql timeout issue, I used c3p0 pool to implement the query.
cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver");
cpds.setJdbcUrl(url);
cpds.setUser(user);
cpds.setPassword(passwd);
cpds.setMaxPoolSize(maxPoolSize);
cpds.setMinPoolSize(minPoolSize);
cpds.setAcquireIncrement(20);
public ResultSet fetch() {
PreparedStatement pst = null;
ResultSet rs = null;
String query = null;
Connection conn = null;
try {
conn = cpds.getConnection();
query = "...";
pst = conn.prepareStatement(query);
rs = pst.executeQuery();
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Query.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
}finally {
try {
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Query.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
}
}
return rs;
}
}
I got this error
SEVERE: Operation not allowed after ResultSet closed java.sql.SQLException: Operation not allowed after ResultSet closed
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1075)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929)
at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:795)
at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7146)
at com.mchange.v2.c3p0.impl.NewProxyResultSet.next(NewProxyResultSet.java:622)
The reason it obvirous, but I am thinking what is the best way to call Mysql query and get results in a function.
In the finally clause, the connection is closed before the method returns.
}finally {
try {
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Query.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
}
}
This Connection is a PooledConnection managed by c3p0. The close() method just return the Connection to pool, without close it. Statements are cleaned-up before the Connection is returned to pool to prevent resource leaks and pool corruption.
When Statements are closed, its current ResultSet object, if one exists, is also closed. Check the java 7 API Statement close() method here
So, the ResultSet is closed when fetch() returns.
Sugestions:
It´s a common addressed problem in java JDBC programming.
First option, code to change fetch() to operate as a template method
public ResultSet fetch(ResultSetIterator rsIterator ) {
PreparedStatement pst = null;
ResultSet rs = null;
String query = null;
Connection conn = null;
try {
conn = cpds.getConnection();
query = "select * from tb_user";
pst = conn.prepareStatement(query);
rs = pst.executeQuery();
rsIterator.iterate(rs);
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Query.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
}finally {
try {
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Query.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
}
}
return rs;
}
ResultSetIterator has the code to process the ResultSet
Second option, use a tool already implemented, like Commons DbUtils, follow the link to see the samples
Other option, use a ER Mapping tool, JPA, hibernate, etc... that abstract the connection handle
Finally, to address the timeout problem and test of connection pooled, use DBCP instead of c3p0, a more robust solution
private static DataSource setupDataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(getDriver());
ds.setUsername(getUser());
ds.setPassword(getPassword());
ds.setUrl(getConnectionString());
ds.setDefaultAutoCommit(false);
ds.setInitialSize(4);
ds.setMaxActive(60);
ds.setMaxIdle(10);
ds.setValidationQuery("/* ping */ SELECT 1");//config to validate against mysql
ds.setValidationQueryTimeout(3);
ds.setTestOnBorrow(true);
ds.setTestOnReturn(true);
return ds;
}
Error stack says that
SEVERE: Operation not allowed after ResultSet closed java.sql.SQLException:
Operation not allowed after ResultSet closed
This error is thrown because, you tried to use the returned instance of ResultSet object,
which is actually released during a database connection close request. And hence you can't use returned ResultSet instance any more constructively.
Documentation says that con.close() "Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be automatically released.". Here JDBC resources means all the Statement objects, ResultSet objects, etc that are created using the connection object that is being closed.
Suggested Solution:
You should define a ResultDataObject class or something meaningful and fill a list of its instances while looping the resultset object in the fetch() method. Sample code snippet is shown below.
public List<ResultDataObject> fetch() {
List<ResultDataObject> list = null; // new ArrayList<ResultDataObject>( 24 );
// ...
rs = pst.executeQuery();
// now prepare the list with results filled and return
if ( list == null ) list = new ArrayList<ResultDataObject>( 24 );
// now read from result set
while ( rs.next() ) {
ResultDataObject resultData = new ResultDataObject(); // or something relevant
// use the following type methods to read from rs and fill result object
resultData.setXXX( rs.getXXX( ... ) );
// ...
list.add( resultData );
} // while rs
// do something if required before return
// ...
return list;
} // fetch()
Thank you everyone for suggestion. I have some ideas and concerns:
1) Run ResultSet rs.close() in the upper level function. But I am not sure whether the connection resource is released or not. It is very important to release the connection resource.
2) create another Object List to temparary save ResultSet structure, and return it to upper level function. My concern is the cost, since I need to create/free the temparary resource twice. It is a problem for large query.
3) create a fake query function "SELECT 1", and run it in upper level function for specific time (e.g. before mysql wait_timeout is triggerred, like every 20 mins). This one will use mysql timeout to close the connection. It is kind of waste mysql resource.
What does oracleClose() and oracleCloseQuery() do in sqlj.runtime.ExecutionContext.OracleContext.
Since we upgraded jdbc driver jar to ojdbc5.jar with the oracleClose() in the finally block we get the below exception when using resultset.next() and not with oracleCloseQuery(). Is it safe to use oracleCloseQuery(). The database is Oracle 11g and WAS 6.1.X.X. Appreciate your response.
Here is the error message :
java.sql.SQLException: Closed Statement: next
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:131)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:197)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:261)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:269)
at oracle.jdbc.driver.OracleResultSetImpl.next(OracleResultSetImpl.java:205)
at com.westgroup.pubsvc.rms.models.ResultSetSRC.getNextResult(ResultSetSRC.java:112)
The exception is telling you that the Statement which has returned this ResultSet is been closed while you're attempting to iterate over the ResultSet. This indicates that you're using ResultSet outside the try block where the Statement is been executed and that you're probably using the ResultSet as return value of the method. This is a bad practice.
I'd suggest you to rewrite your JDBC code so that the ResultSet is been processed in the very same try block as the Statement is been executed, or that the methods returns something like as List<Entity> instead of a ResultSet.
Here's a kickoff example of the correct JDBC idiom:
public List<Entity> list() throws SQLException {
// Declare resources.
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<Entity> entities = new ArrayList<Entity>();
try {
// Acquire resources.
connection = database.getConnection();
statement = connection.createStatement("SELECT id, name, value FROM entity");
resultSet = statement.executeQuery();
// Gather data.
while (resultSet.next()) {
Entity entity = new Entity();
entity.setId(resultSet.getLong("id"));
entity.setName(resultSet.getString("name"));
entity.setValue(resultSet.getInteger("value"));
entities.add(entity);
}
} finally {
// Close resources in reversed order.
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
// Return data.
return entities;
}
By the way, you don't need Oracle JDBC driver specific classes/methods here. It's all just java.sql.*. This way you keep the JDBC code portable among databases.
When using a PreparedStatement in JDBC, should I close the PreparedStatement first or the Connection first? I just saw a code sample in which the Connection is closed first, but it seems to me more logical to close the PreparedStatement first.
Is there a standard, accepted way to do this? Does it matter? Does closing the Connection also cause the PreparedStatement to be closed, since the PreparedStatement is directly related to the Connection object?
The statement. I would expect you to close (in order)
the result set
the statement
the connection
(and check for nulls along the way!)
i.e. close in reverse order to the opening sequence.
If you use Spring JdbcTemplate (or similar) then that will look after this for you. Alternatively you can use Apache Commons DbUtils and DbUtils.close() or DbUtils.closeQuietly().
The following procedures should be done (in order)
The ResultSet
The PreparedStatement
The Connection.
Also, it's advisable to close all JDBC related objects in the finally close to guarantee closure.
//Do the following when dealing with JDBC. This is how I've implemented my JDBC transactions through DAO....
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = ....
ps = conn.prepareStatement(...);
//Populate PreparedStatement
rs = ps.executeQuery();
} catch (/*All relevant exceptions such as SQLException*/Exception e) {
logger.error("Damn, stupid exception: " , e);
} finally {
if (rs != null) {
try {
rs.close();
rs = null;
} catch (SQLException e) {
logger.error(e.getMessage(), e.fillInStackTrace());
}
}
if (ps != null) {
try {
ps.close();
ps = null;
} catch (SQLException e) {
logger.error(e.getMessage(), e.fillInStackTrace());
}
}
try {
if (conn!= null && !conn.isClosed()){
if (!conn.getAutoCommit()) {
conn.commit();
conn.setAutoCommit(true);
}
conn.close();
conn= null;
}
} catch (SQLException sqle) {
logger.error(sqle.getMessage(), sqle.fillInStackTrace());
}
}
You can see I've checked if my objects are null and for connection, check first if the connection is not autocommited. Many people fail to check it and realise that the transaction hasn't been committed to DB.