Java newbie needs help in database connection - java

I'm new to Java and even newer to java database connections. I've managed to create a database connection and query a table when I put it in the Main class. Now that I've moved it into a new class called Connection I am getting errors:
package lokate;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
public class Connection {
private static Statement stmt = null;
private static ResultSet rs = null;
private static Connection con = null;
public Connection() throws SQLException {
try {
Class.forName("com.mysql.jdbc.Driver");
String connectionUrl = "jdbc:mysql://localhost:3306/Lokate?" +
"user=root&password=";
con = DriverManager.getConnection(connectionUrl);
stmt = con.createStatement();
retriveData("SELECT * FROM Users");
int rowsEffected = 0;
} catch (SQLException sqlEx) {
System.out.println("SQL Exception: "+ sqlEx.toString());
} catch (ClassNotFoundException classEx) {
System.out.println("Class Not Found Exception: "+ classEx.toString());
} catch (Exception Ex) {
System.out.println("Exception: "+ Ex.toString());
}
}
public static void retriveData(String SQL) throws Exception {
rs = stmt.executeQuery(SQL);
while (rs.next())
{
System.out.println(rs.getString("fname") + " : " + rs.getString("lname"));
}
}
}
I'm getting an error saying cannot find symbol. Symbol:method createStatement() and incomparable types for con = DriveManager.....
Can anyone help?
Also, is it best practice to put the connection in the class like this then call a new object every time I want to do something with the db?
Regards,
Billy

I'd say your code is an example of many worst practices. Let me count the ways:
Your Connection class is a poor abstraction that offers nothing over and above that of java.sql.Connection.
If you use your class, you'll never get to take advantage of connection pooling.
You hard wire your driver class, your connection URL, etc. You can't change it without editing and recompiling. A better solution would be to externalize such things.
Printing an error message in the catch blocks is far less information than supplying the entire stack trace.
Your code hurts my eyes. It doesn't follow the Sun Java coding standards.
Your retrieveData method is utterly worthless. What will you do with all those printed statements? Wouldn't it be better to load them into a data structure or object so the rest of your code might use that information?
It's rowsAffected - "affect" is the verb, "effect" is the noun. Another variable that's not doing any good.
You're on the wrong track. Rethink it.
I think you'll find this code more helpful.
package persistence;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DatabaseUtils
{
public static Connection createConnection(String driver, String url, String username, String password) throws ClassNotFoundException, SQLException
{
Class.forName(driver);
if ((username == null) || (password == null) || (username.trim().length() == 0) || (password.trim().length() == 0))
{
return DriverManager.getConnection(url);
}
else
{
return DriverManager.getConnection(url, username, password);
}
}
public static void close(Connection connection)
{
try
{
if (connection != null)
{
connection.close();
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public static void close(Statement st)
{
try
{
if (st != null)
{
st.close();
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public static void close(ResultSet rs)
{
try
{
if (rs != null)
{
rs.close();
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public static void rollback(Connection connection)
{
try
{
if (connection != null)
{
connection.rollback();
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public static List<Map<String, Object>> map(ResultSet rs) throws SQLException
{
List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
try
{
if (rs != null)
{
ResultSetMetaData meta = rs.getMetaData();
int numColumns = meta.getColumnCount();
while (rs.next())
{
Map<String, Object> row = new HashMap<String, Object>();
for (int i = 1; i <= numColumns; ++i)
{
String name = meta.getColumnName(i);
Object value = rs.getObject(i);
row.put(name, value);
}
results.add(row);
}
}
}
finally
{
close(rs);
}
return results;
}
}

Your problem is that DriverManager.getConnection returns a java.sql.Connection. Since your class is also called Connection you are getting a name clash between lokate.Connection and java.sql.Connection. You Will need to specify the fully qualified class name where ever you want to use java.sql.Connection, otherwise lokate.Connection is assumed.
Specify fully qualified class name like so:
java.sql.Connection con = null;
// ....
con = DriverManager.getConnection(connectionUrl);
Alternatively, rename your Connection class to something else and you will not get this naming conflict.

Connection is an existing type in the java.sql package, which is what DriverManager.getConnection returns. You have named your class as Connection too, so this is causing the confusion. The simplest way out would be to rename your class to something else and add an import java.sql.Connection; at the top.

Also, is it best practice to put the connection in the class like this then call a new object every time I want to do something with the db?
I think the best practice would be to use an existing solution to this problem, so that you can avoid re-inventing the wheel and focus on what makes your problem unique.
If you are writing a server application (it isn't clear whether you are), then I would also consider using a database connection pool. Creating new database connections on the fly is not efficient and doesn't scale well. You can read about database connection issues in this article I wrote a while back.

Related

SQL connections dangling: Where am I not correctly closing up connections correctly?

I am building a basic java application to load some files into a mysql database. I am able to load the files up and populate my tables without any problems. However after speaking to someone who reviewed my code, I am apparently not correctly closing my connections and wasting resources. Where am I not closing up the connections? Have I done this incorrectly?
I am using the try-with-resources construct within my DbSinger class to execute prepared statements to my database, which should automatically close the connection so long as the AutoCloseable interface is implemented, which it is in the parent class of Db. The close() method however is never reached. The DbSinger is instantiated inside my main() and then runs it's single method populateSingers() with an ArrayList of Singer objects.
Connection Class
public class SQLConnection {
private static final String servername = "localhost";
private static final int port = 3306;
private static final String user = "ng_user";
private static final String pass = "ng";
private static final String db = "ng_music";
private static final String connectionString = "jdbc:mysql://" + servername + ":" + port + "/" + db;
public Connection provide() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection(connectionString, user, pass);
}
catch (SQLException | ClassNotFoundException e) {
throw new SQLConnectionException(e);
}
}
public class SQLConnectionException extends RuntimeException {
SQLConnectionException(Exception e) {super(e);}
}
}
Abstract parent class
public abstract class Db implements AutoCloseable{
private Connection connection;
Db() {
SQLConnection sqlC = new SQLConnection();
this.connection = sqlC.provide();
}
#Override
public synchronized void close() throws SQLException {
if(connection != null) {
connection.close();
connection = null;
System.out.println("Connection closed");
}
}
Connection getConnection() {
return connection;
}
boolean checkIfPopulated(String query){
try {
PreparedStatement ps = getConnection().prepareStatement(query);
ResultSet rs = ps.executeQuery();
return !rs.next();
} catch (SQLException e) {
e.printStackTrace();
}
return true;
}
}
Concrete class to execute queries to database for singers table
public class DbSinger extends Db {
public DbSinger() {
super();
}
public void populateSingers(ArrayList<Singer> singers) {
String populateSingersQuery = "insert into ng_singers(name, dob, sex) values(?,?,?)";
if(!checkIfPopulated("select * from ng_singers")){
System.out.println("Singer Table is already populated");
return;
}
try (PreparedStatement ps = getConnection().prepareStatement(populateSingersQuery)) {
for (Singer s : singers) {
ps.setString(1, s.getName());
ps.setDate(2, java.sql.Date.valueOf(s.getDob()));
ps.setString(3, s.getSex());
ps.addBatch();
}
ps.executeBatch();
System.out.println("Singers added to table");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
My code is able to execute is able to run fine and does what it needs to, but I want to understand why and where I am not closing connections, and to understand how I can resolve this. Or at least understand if I am approaching this wrong.
In your case, you need to instantiate DBSinger class in try-with-resources statement to close the underlying connection.
Instead of doing:
DbSinger dbSinger = new DbSinger();
You need to do:
try (DbSinger dbSinger = new DbSinger()) {
// Your other code
}
This way the close() method you are overriding in your Db class will be called automatically.
Also, close the preparedStatement you created in your checkIfPopulated method by:
try (PreparedStatement ps = getConnection().prepareStatement(query)) {
// Other codes
}
Your code is old way. And you do need close manually. However, with Java 8, you can use try with resource like below,
try (Connection conn = ds.getConnection();
Statement stmt = conn.createStatement()) {
try {
stmt.execute(dropsql);
} catch (Exception ignore) {} // ignore if table not dropped
stmt.execute(createsql);
stmt.execute(insertsql);
try (ResultSet rs = stmt.executeQuery(selectsql)) {
rs.next();
} catch (Exception e2) {
e2.printStackTrace();
return("failed");
}
} catch(Exception e) {
e.printStackTrace();
return("failed");
}

Oracle JDBC UCP and Java

I'm wondering if anyone can shed some light on this topic, as I have been racking my brain for days and can't quite understand why this does not work. I have three classes
main, RetrieveDBVersion,GetOracleConnection I've been doing some testing with oracle JDBC, UCP and Java 1.7.
According to the Oracle documentation, If I use connection pooling the connection will be returned to the pool as soon as I close the connection, Invalidate it and set it to null See Here. So I decided to give it a whirl and see if it would perform just like the documentation says it should. In my Main application I have a simple loop which makes a connection 200 times by calling RetrieveDBVersion. RetrieveDBVersion is simply performing a query and returning the driver version. My loop works fine until I hit the magic number of 68 and then I receive an error which states
java.sql.SQLException: Exception occurred while getting connection:
oracle.ucp.UniversalConnectionPoolException:
Cannot get Connection from Datasource: java.sql.SQLException:
Listener refused the connection with the following error:
ORA-12516, TNS:listener could not find available handler with matching protocol stack
These are the detail of the 3 methods. These methods are not in a server environment. They are simply calling a local oracle express database and I'm running them from my desktop. Why would I keep getting this error? If I'm returning the connections back to the pool?
Main
import com.jam.DB.JDBCVersion;
import static java.lang.System.out;
public class MainApp {
public static void main(String[] args) {
String myMainJDBCVar;
try{
for(int i=1; i<200; i++ )
{
myMainJDBCVar= JDBCVersion.RetrieveDBVersion();
out.println(myMainJDBCVar + " " + i);
}
out.println("this is Done!");
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
RetrieveDBVersion
import java.sql.*;
import oracle.ucp.jdbc.ValidConnection;
public class JDBCVersion {
public static String DBVersion;
public static String RetrieveDBVersion()throws SQLException {
Connection conn = JDBCConnection.GetOracleConnection("test");
try {
DatabaseMetaData meta = conn.getMetaData();
//get driver info
System.out.println("JDBC driver version is " + meta.getDriverMajorVersion());
DBVersion = meta.getDriverVersion();
} catch (SQLException e) {
e.printStackTrace();
DBVersion = e.getMessage();
}
finally {
System.out.println("hit the finally clause");
((ValidConnection) conn).setInvalid();
conn.close();
conn=null;
}
return DBVersion;
}
GetOracleConnection
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
import java.sql.*;
public class JDBCConnection {
public static Connection GetOracleConnection(String Enviroment) throws SQLException{
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
Connection conn = null; //ora.defaultConnection();
try {
pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
pds.setURL("jdbc:oracle:thin:#//localhost:1521/xe");
pds.setUser("system");
//pds.setInitialPoolSize(5);
pds.setPassword("xxx");
pds.setMaxStatements(10);
conn = pds.getConnection();
return conn;
}
catch(Exception e){
e.printStackTrace();
}
return conn;
}
So after careful though and getting a little extra help from the Oracle forum. I finally understand why the above referenced code is giving the error message that I'm receiving. See Here For Response
Because I'm setting the data source everytime the loop goes around, I'm essentially creating more than one pool. The way to do this, is create one pool and than pull connections from that pool.
New code to replace the GetOracleConnection I created a singleton class for datasource and in code I simply retrieve the connection from the data source like such
Connection conn = Database.getInstance().GetPoolSource().getConnection();
package com.jam.DB;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
public class Database {
private static Database dbIsntance;
private static PoolDataSource pds;
private Database() {
// private constructor //
}
public static Database getInstance() {
if (dbIsntance == null) {
dbIsntance = new Database();
}
return dbIsntance;
}
public PoolDataSource GetPoolSource() {
if (pds == null) {
pds = PoolDataSourceFactory.getPoolDataSource();
try {
pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
pds.setURL("jdbc:oracle:thin:#//localhost:1521/xe");
pds.setUser("system");
pds.setPassword("xxxx");
pds.setMaxStatements(15);
return pds;
} catch (Exception e) {
}
return pds;
}
return pds;
}
}

Java and SQL Server

I am new to java, and I am trying to create a method that will retrieve information from the database based on the query that will pass to it.
I thought that I could create by method by creating an object of type:
private Connection controlTableConnection = null;
and then
Statement statement = controlTableConnection.createStatement();
but when I do that piece of code, I get a highlight error:
Unhandled exception
Any help, would be appreciated.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class ConnectMSSQLServer {
private static final String db_connect_string = "jdbc:sqlserver://Cdsx\\SQxxs";
private static final String db_userid = "aa";
private static final String db_password = "bb";
private Connection controlTableConnection = null;
public void dbConnect() {
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection controlTableConnection = DriverManager.getConnection(db_connect_string, db_userid, db_password);
} catch (Exception e) {
e.printStackTrace();
}
}
public void dbDisconnect() {
try {
if (controlTableConnection != null && !controlTableConnection.isClosed()) {
controlTableConnection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void createstatement() {
Statement statement = controlTableConnection.createStatement();
}
}
You have to wrap the createStatement line like below, as you have to handle the SQLException.
try {
Statement statement = controlTableConnection.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
isn't the Connection null? Do you have a driver on the classpath? is the default port correct? Is the sql server live? What kind of exception do you get exactly?
You need to post at least the stack trace or logs

Is a pooled db-access using method-level connection in a static class/method safe?

have been a long-time reader here and now I`ve got a problem I canĀ“t really get my head around.
For ease of access and to save object creation overhead I have a static class realizing database accesses. The used JVM implementation is Tomcat and for connection pooling org.apache.commons.dbcp is used.
I've read a lot about thread-safety, heap and stack here and elsewhere but I can`t get to a definitive conclusion if multiple method calls on my static class won't interfere with each other. Most topics I've read deal with instance methods while I use static ones which might have implications I overlooked.
If I understood everything correctly, as the variables connection, statement, resultset are on the method level, each function call should have a unique reference on the stack to a unique object in the heap and it should not be possible that multiple method calls interfere with each other.
Am I right or do I stand corrected? Any help would be appreciated.
The (shortened) code is :
public class DBQuery{
private static String pathToDataSource = "";
private static javax.naming.Context cxt = null;
private static javax.sql.DataSource ds = null;
private static void getDataSource() throws Exception {
if(pathToDataSource.equals("")){ pathToDataSource = Config.getParam("PathToDataSource"); }
cxt = new javax.naming.InitialContext();
ds = (javax.sql.DataSource) cxt.lookup(pathToDataSource);
}
private static Connection connect() throws Exception {
if(ds==null){ getDataSource(); }
return ds.getConnection();
}
public static Vector doDBquery(String querystring) throws Exception {
Vector retVec = new Vector();
Connection connection = null;
Statement statement = null;
ResultSet resultset = null;
try {
connection = getConnection();
statement = connection.createStatement();
resultset = statement.executeQuery(querystring);
...
} catch(Exception e) {
...
} finally {
myFinallyBlock(resultset, statement, connection);
}
return retVec;
}
// more methods like doDBInsert() following, hence closure in separate myFinallyBlock
private static void myFinallyBlock(ResultSet resultset, Statement statement, Connection connection) {
try {
if (resultset != null) resultset.close();
} catch (SQLException e) { resultset = null; }
try {
if (statement != null) statement.close();
} catch (SQLException e) { statement = null; }
try {
if (connection != null) connection.close();
} catch (SQLException e) { connection = null; }
}
} //close class
Yeah, you are right inside method there is no concurrency problems , until you are using shared variables inside it, in other words "Stateless objects are always thread-safe."
Servlet is quite good example of it ;)
edited.
For making your code safe I recommend you to do follow:
private static Connection connect() throws Exception {
if (ds == null) {
synchronized (Connection.class) {
if (ds == null) {
getDataSource();
}
}
}
return ds.getConnection();
}

Problem in data insertion in Ms access..But Code runs fine

import java.sql.*;
// I think this is a poor abstraction
public class NewConnection {
/*very important: dont use statics for your Connection, Statement and Query objects,
since they can and will be overriden by other Instances of your NewConnection.*/
// There's no need at all for having class members here. It's actually
// a terrible idea, because none of these classes are thread-safe.
private Connection con;
private ResultSet rs;
private Statement sm;
// Better to pass these in.
private final String DRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";
private final String URL = "jdbc:odbc:Driver={Microsoft Access driver (*.mdb)};DBQ=E:\\db1.mdb;DriverID=22";
// private final String URL = "jdbc.odbc.Cooper_Dsn1";
// Another poor idea. Why not just pass this in to the query method?
private static String query;
int i;
private void getConnection(){
try {
Class.forName(DRIVER);
}
catch(ClassNotFoundException e)
// Less information that printing the stack trace.
{System.out.println("Error ="+e);}
try{
System.out.println("Driver Connected");
con=DriverManager.getConnection(URL,"","");
System.out.println("Database Connected");
sm=con.createStatement();
}catch(SQLException e){
System.out.println(e.getMessage());
}
}
// lower case "execute" is the Java convention
private int ExecuteUpdate(String query1)
{ try{
System.out.println(query1);
i=sm.executeUpdate(query1);
con.commit();
}catch(SQLException e){
// No rollback in the event of a failure
System.out.println(e.getMessage());
}
return i;
}
public int executeUpdate(String sql) throws SQLException
{
System.out.println(sql);
con.commit(); // What's this doing? Incorrect
return sm.executeUpdate(sql);
}
// Here's how I might write an update method.
public static int update(Connection connection, String sql)
{
assert connection != null && sql != null;
int numRowsAffected = 0;
PreparedStatement ps = null;
connection.setAutoCommit(false);
try
{
numRowsAffected = ps.execute(sql);
connection.commit();
}
catch (SQLException e)
{
e.printStackTrace();
DatabaseUtils.rollback(connection); // Add this method.
numRowsAffected = 0;
}
finally
{
DatabaseUtils.close(ps);
}
return numRowsAffected;
}
public static void main(String []args) throws SQLException{
NewConnection n= new NewConnection();
n.getConnection();
query="insert into Employee(empid,ename,ephone,email) values('samr','sam','sa','aas');";
System.out.println(n.ExecuteUpdate(query));
}
}
I had modified the code to this....but still has no effect... The query runs successfully but doesn't add data in database. Don't know y..? The code creates the table in database successfully if query changed.
Can any one tell me what is the problem Or Where i m wrong..
You won't see any INSERT with Access until you close your Connection properly.
Your code doesn't close any resources, which will surely bring you grief. Call the close methods in reverse order in a finally block.
public class DatabaseUtils
{
public static Connection createConnection(String driver, String url, String username, String password)
throws ClassNotFoundException, SQLException
{
Class.forName(driver);
return DriverManager.getConnection(url, username, password);
}
public static void close(Connection connection)
{
try
{
if (connection != null)
{
connection.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
public static void close(Statement statement)
{
try
{
if (statement != null)
{
statement.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
public static void close(ResultSet rs)
{
try
{
if (rs != null)
{
rs.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
}

Categories