MysqlConnectionPoolDataSource - Can not insert to mysql db using jdbc? - java

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

Related

Using eclipse to call database from Google Cloud SQL

I m trying to create a dynamic website where I can get data from the database and output it to the user.
I created the connection between MySQL workbench to Google cloud app engine, and I run on the cloud shell to test the database, it works.
But when I try to change the URL on eclipse, it just cannot connect to the server, and gives me errors "Failed to load resource: the server responded with a status of 500 ()".
the URL sting are:
String url = "jdbc:mysql:///film?cloudSqlInstance="
+ "causal-relic-333309:europe-west6:jiayaodb="
+ "&socketFactory = com.google.cloud.sql.mysql.SocketFactory"
+ "&user=root"
+ "&password=password";
private Connection openConnection(){
// loading jdbc driver for mysql
try{
Class.forName("com.mysql.jdbc.Driver");
} catch(Exception e) { System.out.println(e); }
// connecting to database
try{
// connection string for demos database, username demos, password demos
conn = DriverManager.getConnection(url);
stmt = conn.createStatement();
} catch(SQLException se) { System.out.println(se); }
return conn;
}
So I think is the connection error where I can't get it to connect to Google Cloud SQL.
you need to use Cloud SQL proxy to connect to the database from your local machine.

Java MySql Connection Through DSN

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);

DB2 StatementPool configuration issue

I'm trying to activate the statementPool with the db2 jdbc driver, and i m having trouble doing so.
I've tried different techniques mentionned here : http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=%2Fcom.ibm.db2z10.doc.java%2Fsrc%2Ftpc%2Fimjcc_c0052041.htm
Here is the java code :
csUrl += ":maxStatements=1000;";
System.err.println("Connecting to csUrl : " + csUrl);
DB2ConnectionPoolDataSource ds = new DB2ConnectionPoolDataSource();
//DB2SimpleDataSource ds = new DB2SimpleDataSource();
//ds = new DB2ConnectionPoolDataSource();
ds.setServerName("edited");
ds.setPortNumber(edited);
ds.setDatabaseName("edited");
ds.setCurrentSchema("edited");
ds.setMaxStatements(1000);
ds.setDriverType(4);
Connection connection = ds.getPooledConnection(csUser, csPassword).getConnection();
//Connection connection = ds.getConnection(csUser, csPassword);
//Connection connection = DriverManager.getConnection(csUrl);
//Connection connection = m_driver.connect(csUrl, propertiesUserPassword);
boolean pooling = connection.getMetaData().supportsStatementPooling();
if (pooling) {
System.err.println(">>> Pooling is ON!");
} else {
System.err.println(">>> Pooling is OFF! <<<");
}
All techniques fail according to : connection.getMetaData().supportsStatementPooling() and statementPooling is always deactivated.
I'm running DB2 Express /Linux :
Database server = DB2/LINUXX8664 10.1.2
with the matching jdbc driver.
Same code with a different db2 backend (db2 10 zOs) gives the same result, so i guess it s not an Express issue.
Client code is running on windows.
We have a in-house statement cache, but i wanted to play around with DB2's especially since it can apparently share the pool in between logical connections provided thru a PooledDataSource
Thanks :)

Reason for java.sql.SQLException "database in auto-commit mode"

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.

Google Cloud SQL - Error connecting to local database - GAE/J

So Google Cloud SQL has a neat feature where you should be able to connect to your local DB instance for debugging locally as described here:
I've got the following VM arguements:
-Xmx512m -javaagent:C:\eclipse\plugins \com.google.appengine.eclipse.sdkbundle.1.4.2_1.4.2.v201102111811\appengine-java-sdk-1.4.2\lib\agent\appengine-agent.jar
-Drdbms.server=local
-Drdbms.driver=com.mysql.jdbc.Driver
-Drdbms.url=jdbc:mysql://localhost:3306/testdb?user=root&password=pass
I've put the msql driver in the C:\eclipse\plugins \com.google.appengine.eclipse.sdkbundle.1.4.2_1.4.2.v201102111811\appengine-java-sdk-1.4.2\lib\impl folder and added it to the class path.
However when running a simple SELECT query (and this runs fine when deployed on GAE) it tosses the following exception.
java.sql.SQLException: Table not found in statement [SELECT * FROM SOME_TABLE]
Here's the offending code snippet:
Connection c = null;
try {
DriverManager.registerDriver(new AppEngineDriver());
c = DriverManager.getConnection(MY GOOGLE CLOUD SQL CXN STRING);
PreparedStatement ps = c.prepareStatement("SELECT * FROM SOME_TABLE");
ResultSet rs = ps.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
I suspect it's not realizing it has to connect locally, what should I be checking?
Just to mark this as answered: solution provided by Dave W. Smith above
From Dave W. Smiths comment:
I don't know how significant this is to the problem at hand, but 1.4.2
is pretty far out of date.

Categories

Resources