I have a JSP/Servlet based application, the database team is complaining about the increase in open database connection.I suspect that the connection is not closed after use.
I want to make some code changes by initializing the connection string in try catch block as suggested in Java 8
I have tried closing the connection in final block which is working fine
here is the code i want to implement , Will this fix the issue?Is there any other way to close the open connections after use with little code change?
try(Connection con = DBConnectivity.openConnectionThread();
PreparedStatement ps1 = con.prepareStatement(sql1)) {
-----
------
}
You should close also PreparedStatement
try(Connection con = DBConnectivity.openConnectionThread();
PreparedStatement ps1 = con.prepareStatement(sql1))
{
-----
------
}
Related
Currently have a simple Java Program that creates an H2 Database like so:
public static void main(String[] args) {
try {
Connection conn = null;
Statement stm = null;
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection("jdbc:h2:D:/H2db/test", "sa", "sa");
stm = conn.createStatement();
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
I see the files created within the directory. Yet, when attempting to access this same Database from the H2 Console (localhost:8082) and input both
jdbc:h2:D:/H2db/test and jdbc:h2:D:\H2db\test, I get an error saying:
Database `D:/H2db/test` not found, either pre-create it or
allow remote database creation (not recommended in secure environments)
Anyone know why I cant access the Database through the console?
That piece of code is just for connection to a previously created database. To successfully connect to it you should create it first.
$ java -cp bin/h2-1.4.199.jar org.h2.tools.Shell
Welcome to H2 Shell 1.4.199 (2019-03-13)
Exit with Ctrl+C
[Enter] jdbc:h2:mem:test
URL jdbc:h2:D:/h2db/test
[Enter] org.h2.Driver
Driver
[Enter] sa
User
Password
Then and only then you'll be able to connect to it through your java application.
I have to use a custom jdbc connection pooling library to connect to mysql db.
The problem is my that inserts are not persisted in db... To narrow down the issue, I extracted the portion of the library code inserting into db and have some strange findings:
MysqlConnectionPoolDataSource ds1 = new MysqlConnectionPoolDataSource();
ds1.setUser("usr");
ds1.setPassword("pwd");
ds1.setServerName("server");
ds1.setPort(port);
ds1.setDatabaseName("dbname");
ds1.setUseSSL(false);
ds1.setAllowPublicKeyRetrieval(true);
Connection conn = ds1.getPooledConnection("usr", "pwd").getConnection();
logger.info("connection " + conn.toString());
PreparedStatement ps = null;
ResultSet rs = null;
try {
String query = "INSERT INTO ...";
ps = conn.prepareStatement(query);
int timeout = 10;
ps.setQueryTimeout(timeout);
logger.info("timeout: " + timeout);
logger.info("Starting query execution for query: " + query);
long qeStart = System.currentTimeMillis();
ps.setString(1, "...");
ps.executeUpdate();
long qeEnd = System.currentTimeMillis();
logger.info("Query execution completed in " + (qeEnd - qeStart) + "msec.");
} catch (Exception e) {
logger.error("ERROR OCCURED", e);
System.err.println("ERROR OCCURED");
e.printStackTrace();
} finally {
closeResultSet(rs);
closeStatement(ps);
closeConnection(conn);
}
The above code does NOT work when I connect to a remote mysql db with version: 8.0.11-commercial . By not working I mean there is no error, the insert is simply lost...
When I execute the same code against my local mysql db with version : 8.0.11 hosted on windows machine, it is working...
If I change connection getting code from
Connection conn = ds1.getPooledConnection("usr", "pwd").getConnection();
to:
Connection conn = ds1.getConnection();
it also starts to work against remote mysql db with version: 8.0.11-commercial...
The autocommit mode of the underlying connection is already true...
I tried to implement a custom log4j logger with the hope of seeing some trace but that did not help either:
ds1.setLogger("com.ibtech.mysqlproblem.Log4jLogger");
My custom connection pooling library uses pooled connection so I need to get the above code working. In the client I am using mysql-connector-java-8.0.11.jar.
Any help is greatly appreciated...
It seems totally unrelated but setting paranoid property to true seemed to solve my problem...
----------------Edit : Root cause understood---------------------------------------
Problem occurs when global autocommit value is 0 in the server. Issuing change user command, clears session data and autocommit setting is lost.
A workaround solution is to set autocommit flag once again once the connection is acquired...
Thanks to Filipe for analyzing the problem..
https://forums.mysql.com/read.php?39,666702,666986#msg-666986
----------------Edit : Bug created--------------------------------------
It turned out that it is a bug in the JDBC driver. A bug has been filed...
https://bugs.mysql.com/bug.php?id=91351
We have a Java EE application using JPA.
User can ask the app to generate some output (big charts, etc) based on results of a large query, so in that case we decided to use directly JDBC and looping over the resultset.
We have implemented our code like this:
#Resource(mappedName = "jdbc/resource")
private DataSource dataSource;
Connection connection = dataSource.getConnection();
[...]
Connection conn = dataSource.getConnection();
stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
[...]
ResultSet rs = stmt.executeQuery(sql);
while (rs.hasNext()) {
[....]
}
Anyway it always load all the results in memory, we have tried with different techniques (useCursorFetch true and fetch size = 10, etc) with no luck, we always fail to have a stream resultset.
The "jdbc/resource" is the same resource used by jpa entity manager (so it's working fine), the connection have no "weird" options, we are using glassfish 4.1 for our tests and we are using the connector/J version 5.1.26 and 5.1.32.
It there a way to have a working streaming resultset?
I am trying to connect to one of my MySql Databases through a System DSN I set up. The DSN is set up correctly with my SSL certs, username, password, port, and the databases populate the DSN database drop down and the "Test" connection passes. I can't seem to get a connection in Java. I have spent 2 days looking through some examples on Stack but they all refer to an Access database and using JDBC-ODBC bridge which is no longer available in Java 8. I tried using UCanAccess with Jackcess but I have gotten no where. The code below is what I have been tinkering with the last few hours. I normally connect to MySql databases with PHP and receive result in JSON or directly with JDBC driver but for this project neither are really an option. Any ideas. I appreciate the help.
//String username = "<username>";
//String password = "<password>";
//String database = "<database_name>";
try {
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
//Connect to cllients MySql Database
Connection conn = DriverManager.getConnection("jdbc:ucanaccess:" + database);
//Call VerifyLabel(<MAC>,<MODEL>); Call provided client
CallableStatement cStmt = conn.prepareCall("{CALL verify(?, ?)}");
//MAC
cStmt.setString(1, "mac address");
//model
cStmt.setString(2, "model");
cStmt.execute();
//Getting results from "Status" column
ResultSet rs1 = cStmt.getResultSet();
//Iterate results and print.
while (rs1.next()) {
System.out.println(rs1.getString("Status"));
}
//Close connection conn
rs1.close();
} catch (SQLException ex) {
Logger.getLogger(CambiumStoredTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(CambiumStoredTest.class.getName()).log(Level.SEVERE, null, ex);
}
Using MySql Driver:
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql:"+ database);
also tried:
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+ database);
Error for MySql Driver:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
1) DSN is most commonly assocatiated with ODBC (and often with MS-Access). Hence all the links. ODBC is NOT required for a DSN.
2) Do NOT use Ucanaccess. Use J/Connector for mySQL.
3) Make sure you can communicate with mySQL from the command line. Then focus on getting a small "hello world" JDBC app to connect. Your second and third examples look OK. Be sure to check the mySQL logs for any warnings/errors.
Well, after an entire day of trying to get this to work and sleeping on it for a couple hours I finally got it to work. UCanAccess and mysql-connector did not work. The easiest thing since no other method of connecting to this clients database was acceptable was to push this application in Java 7 rather than 8. This allowed me to Coo=nnect to my DSN with no problems. I understand that this method is not the best solution but it is what is working flawlessly and efficiently. Also, instead of using some rigged up 3rd party libs and jars, I am able to use Connector/J. Thanks everyone for trying to help me. Just incase anyone else runs into this issue, this is how I made it work.
Develope app in Java 7 - not 8.
Set Up System DSN
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//You do not need to provide username or password if it is setup in DSN
Connection conn = DriverManager.getConnection("jdbc:odbc:"+ database);
I use sqlite database and java.sql classes in servlet application to batch-insert some data into database.
There are consecutive four inserts of different kinds of data.
Each one looks like this:
PreparedStatement statement = conn
.prepareStatement("insert or ignore into nodes(name,jid,available,reachable,responsive) values(?,?,?,?,?);");
for (NodeInfo n : nodes)
{
statement.setString(1, n.name);
statement.setString(2, n.jid);
statement.setBoolean(3, n.available);
statement.setBoolean(4, n.reachable);
statement.setBoolean(5, n.responsive);
statement.addBatch();
}
conn.setAutoCommit(false);
statement.executeBatch();
conn.commit();
conn.setAutoCommit(true);
statement.close();
But sometimes I get the
java.sql.SQLException: database in auto-commit mode
I found in source code of java.sql.Connection that this exception is thrown when calling commit() while database is in autocommit mode. But I turn autocommit off before and I can't see any place for some parallel execution related issues as for now application is only turned on once.
Do you have any idea how to debug this issue? Maybe there's some other reason for this error (because I just found that exception about database not found or not well configured can be thrown when inserting null into non-null field)?.
May be an issue is with order of statements. Your database statement should be :
PreparedStatement statement1 = null;
PreparedStatement statement2 = null;
Connection connection=null;
try {
//1. Obtain connection and set `false` to autoCommit
connection.setAutoCommit(false);
//2. Prepare and execute statements
statement1=connection.prepareStatement(sql1);
statement2=connection.prepareStatement(sql2);
...
//3. Execute the statements
statement1.executeUpdate();
statement2.executeUpdate();
//4. Commit the changes
connection.commit();
}
} catch (SQLException e ) {
if (connection!=null) {
try {
connection.rollback();
} catch(SQLException excep) {}
}
}finally {
if (statement1 != null) {
statement1.close();
}
if (statement2 != null) {
statement2.close();
}
if(connection != null){
connection.setAutoCommit(true);
connection.close();
}
}
You have to prepare your Statement and create the batch after conn.setAutoCommit(false);.
When running this from a servlet, you have to make sure that the usage of the Connection is synchronized. Multiple requests could set the Connection to a different auto commit mode at nearly the same time. If you use one Connection per request, this will not be an issue. Otherwise, protect the above part with a critical section.
A tip regarding debugging which is applicable for tomcat / eclipse.
1) Enable JDPA debugging for your application server. In tomcat you can do this by adding the following lines to catalina.sh / catalina.bat:
set JPDA_ADDRESS=8000
set JPDA_TRANSPORT=dt_socket
2) Restart the application server
3) Connect with eclipse to your application server. "Debug as" --> "Remote Java Application"
4) Set a break point in above code.
5) Run the servlet.