I know this is a very common issue and we have similar posts in Stackoverflow for the same.
But I am facing same issue in very random order. I do not know how to fix it.
Tried all solutions from this site but no luck
Here is my code
private static Connection conn = null;
private static String connDriverClass;
private static String connDbUrl;
private static String connDbUser;
private static String connDbPassword;
private static Connection getConnection() throws SQLException, ClassNotFoundException {
connDriverClass = "com.sybase.jdbc3.jdbc.SybDriver";
connDbUrl="jdbc:sybase:Tds:some.com:5000/db";
connDbUser="user";
connDbPassword="pass";
if(conn !=null && !conn .isClosed()) { return conn ; }
try {
Class.forName(connDriverClass);
viTechConn = DriverManager.getConnection(connDbUrl, connDbUser, connDbPassword);
} catch (SQLException | ClassNotFoundException e) {
LOG.error("Error in getting DB Connection "+e.getMessage());
throw e;
}
return conn;
}
We run it in parallel processes.
It works fine sometimes and sometimes it gives error saying
java.sql.SQLException: No suitable driver found for jdbc:sybase:Tds:some.com:5000/db
Please tell me how to overcome this random behavior.
Thanks.
You can consider using a pooled data source, instead. Its a one time effort and will save a lot of debugging efforts in the future.
Refer to the following class file implementation, on how to create and access a pooled data source.
http://www.programcreek.com/java-api-examples/index.php?source_dir=jasperserver-master/5.5/com/jaspersoft/jasperserver/api/engine/jasperreports/service/impl/JdbcReportDataSourceServiceFactory.java
Related
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.
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.
We are developing a new desktop application in JavaFx wherein for offline storage we are using SQLite and for orm we are using ormlite.
I want to implement DB connection pooling wherein a fixed number of connections should be set at the start and should be used, released and reused as required. Also, it would be good if we can make use of "readonly" and "writeonly" connections appropriately to maximize performance.
This is what we have written so far.
public class DAO {
private static JdbcPooledConnectionSource connectionSource;
private static DAO instance = null;
private DAO() throws SQLException {
try {
final File path = SystemUtils.getDatabaseFile();
final String DATABASE_URL = Constants.DATABASE_URL + path.getAbsolutePath();
Class.forName(Constants.DATABASE_DRIVER);
connectionSource = new JdbcPooledConnectionSource(DATABASE_URL);
//connectionSource.setMaxConnectionAgeMillis(5 * 60 * 1000);
connectionSource.setCheckConnectionsEveryMillis(5000);
connectionSource.setMaxConnectionsFree(5);
connectionSource.initialize();
init();
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void init() throws ClassNotFoundException, SQLException {
TableUtils.createTableIfNotExists(connectionSource, Customer.class);
TableUtils.createTableIfNotExists(connectionSource, Address.class);
TableUtils.createTableIfNotExists(connectionSource, Location.class);
TableUtils.createTableIfNotExists(connectionSource, City.class);
TableUtils.createTableIfNotExists(connectionSource, Area.class);
TableUtils.createTableIfNotExists(connectionSource, Category.class);
TableUtils.createTableIfNotExists(connectionSource, Product.class);
TableUtils.createTableIfNotExists(connectionSource, AddonCategory.class);
TableUtils.createTableIfNotExists(connectionSource, ProductAddon.class);
}
public synchronized <D extends Dao<T, ?>, T> D getDao(Class<T> cls) throws SQLException {
Dao<T, ?> dao = DaoManager.createDao(connectionSource, cls);
D daoImpl = (D) dao;
return daoImpl;
}
public synchronized static DAO getInstance() throws SQLException {
if (instance == null) instance = new DAO();
return instance;
}
}
The problem here is everytime we are creating table (TableUtils.createTableIfNotExists) the pooled connection source is making a new connection and not reusing the one earlier used/created.
Not finding enough code examples on Internet on how to correctly use JdbcPooledConnectionSource.
JdbcPooledConnectionSource correct usage
Which SQLite driver are you using? The Xerial driver has the Sqlite code actually compiled into the Jar. This means that you really aren't "connecting" to another database just making calls to the database directly even though it is fronted by a JDBC interface.
This means that you really don't need a JdbcPooledConnectionSource. The pooled connections really only help when you are making connections over the network to a database server. If you look at your application, you should see file-descriptors (in /prod/#/fd if in Linux) which show open FDs to the database but not to sockets.
The problem here is everytime we are creating table (TableUtils.createTableIfNotExists) the pooled connection source is making a new connection and not reusing the one earlier used/created.
Hrm. I have some good coverage in unit tests around the pooled connection source. I'm surprised to hear that it isn't reusing connections. Can you get me a unit test to demonstrate it?
I have a basic code snippet below but it is not working.What may be the problem with it.
public List<String> getStores() throws SQLException{
List<String> store_id=new ArrayList<>();
String query="select distinct(store_id) from stores";
Connection con=ConnectDatabase.getDb2ConObj();
Statement stmt=con.createStatement();
java.sql.ResultSet rsResultSet=stmt.executeQuery(query);
while(rsResultSet.next()){
store_id.add(rsResultSet.getString(1));
}
con.close();
return store_id;
}
It is throwing the below exception
com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:888)
at com.mysql.jdbc.Connection.checkClosed(Connection.java:1931)
at com.mysql.jdbc.Connection.createStatement(Connection.java:3087)
at com.mysql.jdbc.Connection.createStatement(Connection.java:3069)
at com.dao.StoreDao.getStores(StoreDao.java:52)
at org.apache.jsp.adminViewAllStore_jsp._jspService(adminViewAllStore_jsp.java:119)
The code for ConnectDatabse is
public class ConnectDatabase {
static Connection con=null;
static String connectionString="jdbc:mysql://localhost:3306/ayurveda";
static String username="root";
static String password="";
public static Connection getDb2ConObj(){
if(con==null){
try{
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection(connectionString,username,password);
}
catch(ClassNotFoundException | SQLException e)
{
System.out.println("Connect initialized with error"+e.getMessage());
e.printStackTrace();
}
}
return con;
}
I cannot understand the reason for the same.What may be the problem.Since I am closing the connection after I am done with it.
It worked after I enclosed it in a try catch finally block.Changed the code as given below
public List<String> getStores() throws SQLException{
List<String> store_id=new ArrayList<>();
Connection con=ConnectDatabase.getDb2ConObj();
try{
String query="select distinct(store_id) from stores";
Statement stmt=con.createStatement();
java.sql.ResultSet rsResultSet=stmt.executeQuery(query);
while(rsResultSet.next()){
store_id.add(rsResultSet.getString(1));
}
}catch(Exception e){
}finally{
con.close();
}
return store_id;
}
Thanks.
You can use this type of code...for solving your problem
public void actionPerformed(ActionEvent ae)
{
String u=t1.getText();
String p=t2.getText();
if(ae.getSource()==b1)
{
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con=DriverManager.getConnection("jdbc:odbc:newdsn");
String stp="SELECT * FROM reg";
Statement sa=con.createStatement();
rs=sa.executeQuery(stp);
while(rs.next())
{
String du=rs.getString(2);
String dp=rs.getString(3);
if(du.equals(u)&&dp.equals(p))
{
a=0;
break;
}else{ a=1;}
}
if(a==0){
JOptionPane.showMessageDialog(this,"LOGIN PAGE","Login is successful",1);
}
if(a==1){
JOptionPane.showMessageDialog(this,"LOGIN PAGE","Login is not successful",1);
}}
catch(Exception e){}
}}
if even the it is throwing exception then you check the system 32 bit or 64 bit..you should try if 64bit then please make your dsn in 32 bit and anduse ms access 2002-2003 version
then you get tour solution .....thank u
Use Java 7 -The try-with-resources Statement
According to the oracle documentation, you can combine a try-with-resources block with a regular try block
The typical Java application manipulates several types of resources such as files, streams, sockets, and database connections. Such resources must be handled with great care, because they acquire system resources for their operations. Thus, you need to ensure that they get freed even in case of errors.
Indeed, incorrect resource management is a common source of failures in production applications, with the usual pitfalls being database connections and file descriptors remaining opened after an exception has occurred somewhere else in the code. This leads to application servers being frequently restarted when resource exhaustion occurs, because operating systems and server applications generally have an upper-bound limit for resources.
sample code:
try(Connection con = getConnection()) {
...
}
Read more Java 7 Automatic Resource Management JDBC
Close Statement and ResultSet as well.
Don't load driver class every time when connection is needed. Just load it once in static initialization block.
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
I suggest you to use JNDI and DataSource to keep username and password outside the Java code to make it more manageable. Keep the database configuration in a separate xml/properties file instead of hard-coding in Java file.
See Java Tutorial on Connecting with DataSource Objects
I have already posted a nice ConnectionUtil class to manage all the connections in a single class for whole application.
I am creating a java application that connects to multiple databases. A user will be able to select the database they want to connect to from a drop down box.
The program then connects to the database by passing the name to a method that creates an initial context so it can talk with an oracle web logic data source.
public class dbMainConnection {
private static dbMainConnection conn = null;
private static java.sql.Connection dbConn = null;
private static javax.sql.DataSource ds = null;
private static Logger log = LoggerUtil.getLogger();
private dbMainConnection(String database) {
try {
Context ctx = new InitialContext();
if (ctx == null) {
log.info("JDNI Problem, cannot get InitialContext");
}
database = "jdbc/" + database;
log.info("This is the database string in DBMainConnection" + database);
ds = (javax.sql.DataSource) ctx.lookup (database);
} catch (Exception ex) {
log.error("eMTSLogin: Error in dbMainConnection while connecting to the database : " + database, ex);
}
}
public Connection getConnection() {
try {
return ds.getConnection();
} catch (Exception ex) {
log.error("Error in main getConnection while connecting to the database : ", ex);
return null;
}
}
public static dbMainConnection getInstance(String database) {
if (dbConn == null) {
conn = new dbMainConnection(database);
}
return conn;
}
public void freeConnection(Connection c) {
try {
c.close();
log.info(c + " is now closed");
} catch (SQLException sqle) {
log.error("Error in main freeConnection : ", sqle);
}
}
}
My problem is what happens if say someone forgets to create the data source for the database but they still add it to the drop down box? Right now what happens is if I try and connect to a database that doesn't have a data source it errors saying it cannot get a connection. Which is what I want but if I connect to a database that does have a data source first, which works, then try and connect to the database that doesn't have a data source, again it errors with
javax.naming.NameNotFoundException: Unable to resolve 'jdbc.peterson'. Resolved 'jdbc'; remaining name 'peterson'.
Which again I would expect but what is confusing me is it then grabs the last good connection which is for a different database and process everything as if nothing happened.
Anyone know why that is? Is weblogic caching the connection or something as a fail safe? Is it a bad idea to create connections this way?
You're storing a unique datasource (and connection, and dbMainConnection) in a static variable of your class. Each time someone asks for a datasource, you replace the previous one by the new one. If an exception occurs while getting a datasource from JNDI, the static datasource stays as it is. You should not store anything in a static variable. Since your dbMainConnection class is constructed with the name of a database, and there are several database names, it makes no sense to make it a singleton.
Just use the following code to access the datasource:
public final class DataSourceUtil {
/**
* Private constructor to prevent unnecessary instantiations
*/
private DataSourceUtil() {
}
public static DataSource getDataSource(String name) {
try {
Context ctx = new InitialContext();
String database = "jdbc/" + name;
return (javax.sql.DataSource) ctx.lookup (database);
}
catch (NamingException e) {
throw new IllegalStateException("Error accessing JNDI and getting the database named " + name);
}
}
}
And let the callers get a connection from the datasource and close it when they have finished using it.
You're catching JNDI exception upon lookup of the nonexistent datasource but your singleton still keeps the reference to previously looked up datasource. As A.B. Cade says, null reference to ds upon exception, or even before that.
On a more general note, perhaps using Singleton is not the best idea.