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);
}
}
}
Related
I've got problem with connection to hsqldb using jdbc in java app. After parsing in main class from json to java I get 3 objects in list which i am trying to save to database.
Here is Dao class
public class EventDao {
private static final String URL = "jdbc:hsql:file:C:/Applications/appName//APPFOLDER";
private static final String USER = "sa";
private static final String PASS = "";
private Connection connection;
public EventDao() {
try {
Class.forName("org.hsqldb.jdbcDrive");
connection = DriverManager.getConnection(URL, USER, PASS);
} catch (ClassNotFoundException e) {
System.out.println("Couldnot establish connection");
} catch (SQLException e) {
e.printStackTrace();
}
}
public void save(Event event) {
final String sql = "insert into event(id,state,timestamp,type,host,alert) values (?,?,?,?,?,?)";
try {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, event.getId());
preparedStatement.setString(2, event.getState());
preparedStatement.setString(3, event.getTimestamp().toString());
preparedStatement.setString(4, event.getType());
preparedStatement.setString(5, event.getHost());
preparedStatement.setString(6, event.getAlert().toString());
preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void close() {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
And here is main when i am trying to save object Event to db (the list have 3 objects)
public static void main(String[] args) {
EventParser eventParser = new EventParser();
eventParser.mainLoop();
}
public void mainLoop() {
try {
EventDao eventDao = new EventDao();
Map<String, EventWrapper> eventsFromFile = readEventsFromFile();
List<Event> eventsToSave = calculateEventTime(eventsFromFile);
for (Event event : eventsToSave) {
eventDao.save(event);
}
eventDao.close();
System.out.println(eventsFromFile);
} catch (IOException e) {
e.printStackTrace();
}
}
After debuging i found out that connection is null. Any ideas why?
The correct form of the URL is:
URL = "jdbc:hsqldb:file:C:/Applications/appName/APPFOLDER";
The Class.forName("org.hsqldb.jdbcDrive") ensures the HSQLDB jar is on your classpath and loads the JDBC driver class form the jar. This was done without error. The error message indicates there is no driver available for the incorrect jdbc:hsql:file url.
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");
}
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
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();
}
I'm stuck on something, and can't seem to think of a solution. I have a function called dbSelect, which then creates a thread to run a MySQL query and get a ResultSet, but then I need my dbSelect to get that ResultSet and return it. Here's what I have:
public class Utils {
public static void dbSelect(String query){
selectQuery = query;
Thread selectThread = new selectThreadClass();
selectThread.start();
}
}
class selectThreadClass extends Thread {
public void run(){
perform();
}
public ResultSet perform(){
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection("jdbc:mysql://localhost/lob/?user=root&password=");
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(Utils.selectQuery);
return rs;
}catch (SQLException | InstantiationException | IllegalAccessException | ClassNotFoundException e){
e.printStackTrace();
return null;
}
}
}
Can anyone help me get it so that dbSelect returns the ResultSet from the thread? Thanks!
Use Callable
public interface Callable<V> {
V call() throws Exception;
}
Instead of Runnable Use callable.
public class SelectCallableClass implements Callable<ResultSet> {
public ResultSet call() throws Exception {
return perform();
}
public ResultSet perform(){
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection("jdbc:mysql://localhost/lob/?user=root&password=");
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(Utils.selectQuery);
return rs;
}catch (SQLException | InstantiationException | IllegalAccessException | ClassNotFoundException e){
e.printStackTrace();
return null;
}
}
}
To submit Callable class, use the ExecuterService
ExecutorService service=Executors.newFixedThreadPool(1);
Future future=service.submit(new SelectCallableClass());
The above code does the following(from doc).Submits a value-returning task for execution and returns a Future> representing the pending results of the task. The Future's get method
will return the task's result upon successful completion.
just a try from my end
I modified the code and got the solution using List to hold the value from the ResultSet but I just have one question
and that is, I was not able to get the result as type (ResultSet) in Callable
Somehow the result set was empty when I tried to
retrieve the value using the future get() function
ResultSet rs = (ResultSet)future.get();
Below is the piece of code which didnt work,
ExecutorService service=Executors.newFixedThreadPool(1);
Callable<ResultSet> callable = new SelectThreadResultSet();
Future<ResultSet> future = service.submit(callable);
ResultSet rs = (ResultSet)future.get();
// Here I dont get any values
while(rs.next()){
System.out.println(rs.getString("EMPLOYEE"));
}
Please find below the solution which worked for me, I used List
to hold the values and returned it.
class SelectThreadClass:
public class SelectThreadClass implements Callable<List<String>> {
public List<String> call(){
ResultSet rs = null;
List<String> strList = new ArrayList<String>();
try {
rs = perform();
while(rs.next()){
strList.add(rs.getString("EMPNAME"));
}
System.out.println("Passed");
} catch (InstantiationException | IllegalAccessException | SQLException e) {
e.printStackTrace();
}
return strList;
}
public ResultSet perform() throws InstantiationException, IllegalAccessException, SQLException{
Connection conn = null;
try {
Class.forName("org.sqlite.JDBC");
try {
conn = DriverManager.getConnection("jdbc:sqlite:C:\\SqlLite\\EMPLOYEE.db");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Statement s = null;
try {
s = conn.createStatement();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ResultSet rs = null;
try {
rs = s.executeQuery(Utils.selectQuery);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rs;
}catch (ClassNotFoundException e){
e.printStackTrace();
return null;
}
}
}
class Utils:
public class Utils {
public static String selectQuery = "SELECT EMPNAME FROM EMPLOYEEDETAILS";
public static void dbSelect(String query) throws InterruptedException, ExecutionException, SQLException{
ExecutorService service=Executors.newFixedThreadPool(1);
Callable<List<String>> callable = new SelectThreadClass();
Future<List<String>> future = service.submit(callable);
List<String> empList = future.get();
for(String emp : empList){
System.out.println(emp);
}
}
public static void main(String args[]) throws InterruptedException, ExecutionException, SQLException{
dbSelect("SELECT EMPNAME FROM EMPLOYEEDETAILS");
}
}
run does not return a result.
Either use al Callable or use a shared variable and poll/wait in Utils until the result from the SelectThreadClass is available.
But I recommend to use a Callable as it fits exactly for the task
You can simply have an attribute in your Thread class and then get hold of that attribute,
public class Utils {
public static void dbSelect(String query){
selectQuery = query;
Thread selectThread = new selectThreadClass();
selectThread.start();
((SelectThreadClass) selectThread).getResult();
}
}
class selectThreadClass extends Thread {
ResultSet rs = null;
public ResultSet getResult(){
return rs;
}
public void run(){
rs = perform();
}
public ResultSet perform(){
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection("jdbc:mysql://localhost/lob/?user=root&password=");
Statement s = conn.createStatement();
return s.executeQuery(Utils.selectQuery);
} catch (SQLException | InstantiationException | IllegalAccessException | ClassNotFoundException e){
e.printStackTrace();
return null;
}
}
}
the only problem is that you might end up handling the connection closure and other stuff out of your dbutil, alternatively , you can convert the result set to whatever java class and then return that java object list rather result set