MYSQL shows too many processes from java application - java

i have a java application which connects to mysql database using MYSQL connector. problem is when application started, MYSQL process list shows many connections than i requested in process list (attached image).
i have two threads running which connects to database within 5 seconds and 11 seconds. but, when i refresh mysql process list, it shows server's host ports are changing rapidely than threads are running. normally its changing 3-5 ports per second. can someone please guide me any optimizing issues or any changes to test with this?
thanks
P.S.
I have created a class which connects to DB at initialization and that class's object is in a places where needs DB connectivity. and that class having all methods which using to query from DB.
EDIT
my database connectivity class code is
public class Data{
static Connection con; //create connection
static Statement stmt; //create statement
static ResultSet rs; //create result set
static HostRead hr = new HostRead();
static int db_port = 3306;
static String db_root = "127.0.0.1";
static String db_name = "chsneranew";
static String db_user = "root";
static String db_pass = "";
/**Constructer method*/
public Data(){
this(db_root,db_port,db_name,db_user,db_pass);
if(getConnection()==null){
System.out.println("error in database connection");
}
else{
con = getConnection();
}
}
protected void finalize() throws Throwable {
try {
System.out.println("desctroyed");
con.close();
} finally {
super.finalize();
}
}
public static Connection getConnection(){
try{
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection conn = DriverManager.getConnection("jdbc:mysql://"+db_root+":"+db_port+"/"+db_name, db_user, db_pass);
stmt = conn.createStatement();
return conn;
}
catch(ClassNotFoundException er){
JOptionPane.showMessageDialog(null,"Error found ...\nDataBase Driver error (Invalid Drivers)\nUsers Cant login to system without database\n\nContact System Administrator","Error",JOptionPane.ERROR_MESSAGE);
return null;
}
catch(Exception er){
JOptionPane.showMessageDialog(null,"Error found ...\nDataBase Access error (Invalid Authentication)\nOr\nDataBase not found. Details are not be loaded \n\nUsers Cant login to system without database\n\nContact System Administrator","Error",JOptionPane.ERROR_MESSAGE);
return null;
}
}
public String getUserName(){
try{
Statement stmt2 = getConnection().createStatement();
ResultSet rss2;
String sql = "SELECT name FROM gen";
rss2 = stmt2.executeQuery(sql);
if(rss2.next()){
return rss2.getString("name");
}
}
catch(Exception er){
er.printStackTrace();
}
return null;
}
}
i am calling getUserName()method in my threads. using
Data d = new Data();
d.getUserName();

conn.close();
You need to close the connection, the connection is not closed that is why it is still there in the list. You need to Connection conn above so that it may be visible to rest of the code.

You are calling the getConnection() method three times when you want to read the data via the getUserName() method. Two times in the constructor when your constructor of the Data class is called (one for the if(...) check, one for the con = getConnection() line) and one time when you actually want to read the data at the getConnection().createStatement() line. So you have three connections to the database, and that is just the getUserName method...
Rewrite your code that only one connection is established and this connection is reused for any further execution.

Related

Tomcat doesn't sync with the mysql database

I'm currently working on a college project, and I'm creating a very simple e-commerce style website.
I'm using JDBC driver manager and connection pool for the connection to the db, while using Tomcat 9.0 as the container.
The problem is: when I modify some product through the website (let's say the amount available for example), the website doesn't always reflect the changes, while I can always see the data correctly in MySql Workbench.
It actually works one time out of two on the same query:
I run the query for the first time after the changes -> it shows the old value
I run the query for the second time after the changes -> it shows the new value
I run the query for the third time after the changes -> it shows the old value
And so on.
I've already tried to set caching off (from the query, using the SQL_NO_CACHE), but it didn't seem to solve the problem, I've tried to use Datasource instead, but it causes other problems that most likely I won't have the time to solve.
This is the connection pool file, which I think might be problem, I'm not that sure tho:
public class DriverManagerConnectionPool {
private static List<Connection> freeDbConnections;
static {
freeDbConnections = new LinkedList<Connection>();
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("DB driver not found:"+ e.getMessage());
}
}
private static synchronized Connection createDBConnection() throws SQLException {
Connection newConnection = null;
String ip = "localhost";
String port = "3306";
String db = "storage";
String username = "root";
String password = "1234";
newConnection = DriverManager.getConnection("jdbc:mysql://"+ ip+":"+ port+"/"+db+"?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", username, password);
newConnection.setAutoCommit(false);
return newConnection;
}
public static synchronized Connection getConnection() throws SQLException {
Connection connection;
if (!freeDbConnections.isEmpty()) {
connection = (Connection) freeDbConnections.get(0);
freeDbConnections.remove(0);
try {
if (connection.isClosed())
connection = getConnection();
} catch (SQLException e) {
connection.close();
connection = getConnection();
}
} else {
connection = createDBConnection();
}
return connection;
}
public static synchronized void releaseConnection(Connection connection) throws SQLException {
if(connection != null) freeDbConnections.add(connection);
}
}
I really hope you can help me, I haven't found any solution online!
I guess it is because of auto-commit is disabled. Please try using #Transactional or set auto-commit to true. You can also try to use db.commit after each statement.
As per your connection pool implementation, all connection in your pool seems to be auto committed false.
Please check you have properly committed the connection after executing the query or not.
So it might be the case that, when executing the query after changes with same connection it reflects those changes, done earlier and on other connections, old values are might get returned.

H2 Database, problems getting data from tables

I'm creating a JavaFX application, I've connected to the database fine. However when i look to get data from the tables i get the error
org.h2.jdbc.JdbcSQLException: Table "LECTURE" not found; SQL
statement: SELECT NAME FROM Lecture [42102-192]
and I'm 100% sure i'm connected to the database and the table is definitely there, any suggestions on why this is?
hear is my connection code and the code i am running just so you can see
public class ConnectionFactory {
//static reference to itself
private static ConnectionFactory instance = new ConnectionFactory();
public static final String URL = "jdbc:h2:file:~/db\\.";
public static final String USER = "notepad";
public static final String PASSWORD = "password";
public static final String DRIVER_CLASS = "org.h2.Driver";
//private constructor
private ConnectionFactory() {
try {
Class.forName(DRIVER_CLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private Connection createConnection() {
Connection connection = null;
try {
connection = DriverManager.getConnection(URL, USER, PASSWORD);
} catch (SQLException e) {
System.out.println("ERROR: Unable to Connect to Database.");
}
return connection;
}
public static Connection getConnection() {
return instance.createConnection();
}
}
And the query being run
private void onLoadYearSelect() {
try {
Connection con = ConnectionFactory.getConnection();
Statement stat = con.createStatement();
String query = "SELECT NAME FROM Lecture";
ResultSet years = stat.executeQuery(query);
while(years.next()){
yearSelect.setValue(years.getString("NAME"));
System.out.println(years.getString("NAME"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void initialize(){
onLoadYearSelect();
}
If it says the table doesn't exist, then it really doesn't exist.
Most likely, you are not actually connecting to the correct database. In fact, by default, if the connection string points to a non-existent database, it just creates an empty database on the fly, which would explain your error.
It's probably too late now (because there is probably a 2nd database created already somewhere), but to avoid this confusion, it's not a bad idea to include IFEXISTS=TRUE in the connection string so that it fails if the database doesn't exist, rather than creating an empty one that will mask the true problem.
public static final String URL = "jdbc:h2:file:~/db\\.;IFEXISTS=TRUE";
However, one thing you can still try to debug the problem, is to add IFEXISTS=TRUE to the connection string. Then move or rename the database you think it should be connecting to so as to make the connection string invalid. Basically, force it to fail. If the code still connects to the database successfully, then you'll know the connection string is not pointing to the location you think it is.

how to take database as parameter to connect to mysql database server

import java.sql.*;
class ConnectSql
{
static Connection cont(String db)throws Exception
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/"+db+","root","xyz" );
return(con);
}
}
I am facing a problem in compiling this function and this 7th line is i suppose a problem is there an syntax error.If so please tell me.Here i want to take the name of database as parameter received from calling function.When i gave the exact name of database instead of parameter it worked,but not after i passed parameter in connection line.
it should be
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/"+db,"root","xyz" );
problem is
"+db+"
you have extra " mark
Connection con=null;
String DB_URL = "jdbc:mysql://localhost:3306/";
String USER = "abc";//db user name
String PASS = "abc";//db password
public synchronized Connection getConnection(String dbname)
{
try
{
Class.forName("com.mysql.jdbc.Driver");//loading mysql driver
con = DriverManager.getConnection(DB_URL+dbname,USER,PASS);//connecting to mysql
}
catch(Exception e)
{
e.printStackTrace();
}
return con;
}

Create a class to connect to any database using jdbc

I am trying to design a Java swing application. I want to experiment and use an MVC type of architecture whereby my UI is separated from the actual logic to access data and connect to a database. I have decided that I need to create a custom class that contains all the logic to connect to the database and then simply call methods from this class in my action event for any particular form and button. This way I can switch databases and all I need to do (if I have a large code base with many many forms) is change the JDBC connection string to connect to oracle instead of MySQL. So far I have the code to connect to a database but I am trying to figure out how I can make this a class.
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=(Connection)DriverManager.getConnection("jdbc:mysql://localhost:3306/prototypeeop","root","triala");
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery(sql);
I will then return the result set from a member function of my connection class to process and display on the screen.
Just create a separate class and delegate to him a getting of connection to database:
public class ConnectionManager {
private static String url = "jdbc:mysql://localhost:3306/prototypeeop";
private static String driverName = "com.mysql.jdbc.Driver";
private static String username = "root";
private static String password = "triala";
private static Connection con;
private static String urlstring;
public static Connection getConnection() {
try {
Class.forName(driverName);
try {
con = DriverManager.getConnection(urlstring, username, password);
} catch (SQLException ex) {
// log an exception. fro example:
System.out.println("Failed to create the database connection.");
}
} catch (ClassNotFoundException ex) {
// log an exception. for example:
System.out.println("Driver not found.");
}
return con;
}
}
Then get the connection in a code as follows:
private Connection con = null;
private Statement stmt = null;
private ResultSet rs = null;
con = ConnectionManager.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery(sql);
You can try MySQL JDBC Utilities API for MySQL connectivity.
This API offers very cool features and also fulfill your requirement!
Two ways you can make it
Override determineCurrentLookupKey() method of Spring's AbstractRoutingDataSource class.
You can create a class which will return Connection based on system.
You can either use fancier stuff like Hibernate or if your database usage is simple then you can try Commons DbUtils
Ceremonial connection code
String db = "jdbc:h2:mem:;INIT=runscript from 'classpath:/prototypeeop.sql'";
//for H2 in-memory database:
Connection DriverManager.getConnection(db);
Remember the core classes and interfaces in Commons DbUtils are QueryRunner and ResultSetHandler.

Store database connection as separate Class - Java

Is it possible to store a database connection as a separate class, then call the database objects from a main code? ie;
public class main{
public static void main{
try{
Class.forName("com.jdbc.driver");
Database to = new Database(1,"SERVER1","DATABASE");
Database from = new Database(2,"SERVER2","DATABASE");
String QueryStr = String.format("SELECT * FROM TABLE WHERE Id = %i", to.id)
to.results = sql.executeQuery(QueryStr);
while (to.results.next()) {
String QueryStr = String.format("INSERT INTO Table (A,B) VALUES (%s,%s)",to.results.getString(1),to.results.getString(2));
from.sql.executeQuery("QueryStr");
}
to.connection.close()
from.connection.close()
} catch (Exception ex) {
ex.printStackTrace();
{ finally {
if (to.connection != null)
try {
to.connection.close();
} catch (SQLException x) {
}
if (from.connection != null)
try {
from.connection.close();
} catch (SQLException x) {
}
}
}
public static class Database {
public int id;
public String server;
public String database;
public Connection connection;
public ResultSet results;
public Statement sql;
public Database(int _id, String _server, String _database) {
id = _id;
server = _server;
database = _database;
String connectStr = String.format("jdbc:driver://SERVER=%s;port=6322;DATABASE=%s",server,database);
connection = DriverManager.getConnection(connectStr);
sql = connection.createStatement;
}
}
}
I keep getting a "Connection object is closed" error when I call to.results = sql.executeQuery("SELECT * FROM TABLE"); like the connection closes as soon as the Database is done initializing.
The reason I ask is I have multiple databases that are all about the same that I am dumping into a master database. I thought it would be nice to setup a loop to go through each from database and insert into each to database using the same class. Is this not possible? Database will also contain more methods than shown as well. I am pretty new to java, so hopefully this makes sense...
Also, my code is probably riddled with syntax errors as is, so try not to focus on that.
Connection object is closed doesn't mean that the connection is closed, but that the object relative to the connection is closed (it could be a Statement or a ResultSet).
It's difficult to see from your example, since it has been trimmed/re-arranged, but it looks like you may be trying to use a ResultSet after having re-used its corresponding Statement. See the documentation:
By default, only one ResultSet object per Statement object can be open
at the same time. Therefore, if the reading of one ResultSet object is
interleaved with the reading of another, each must have been generated
by different Statement objects. All execution methods in the Statement
interface implicitly close a statment's current ResultSet object if an
open one exists.
In your example, it may be because autoCommit is set to true by default. You can override this on the java.sql.Connection class. Better yet is to use a transaction framework if you're updating multiple tables.

Categories

Resources