Useful piece of code for Hive JDBC:
Connection con = null;
Statement stmt = null
try {
Class.forName("org.apache.hive.jdbc.HiveDriver");
con = DriverManager.getConnection(connectionUri, userName, password);
stmt = con.createStatement();
stmt.executeUpdate(query);
} catch (ClassNotFoundException cex) {
cex.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
I want to remove try - catch in finally block.
So I tried The try-with-resources Statement.
try (Class.forName("org.apache.hive.jdbc.HiveDriver");
Connection con = DriverManager.getConnection(connectionUri, userName, password);
Statement stmt = con.createStatement();){
stmt.executeUpdate(query);
} catch (ClassNotFoundException cex) {
cex.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
I think this is not the right way.
Class.forName("org.apache.hive.jdbc.HiveDriver") should not be in try. Should I make a separate try-catch for this?
try {
Class.forName("org.apache.hive.jdbc.HiveDriver");
} catch (ClassNotFoundException cex) {
cex.printStackTrace();
}
try (Connection con = DriverManager.getConnection(connectionUri, userName, password);
Statement stmt = con.createStatement();){
stmt.executeUpdate(query);
} catch (SQLException e) {
e.printStackTrace();
}
Is this right way or am I missing any thing?
The idea behind try-with-ressource is to close an AutoCloseable class.
So every usage of a class which should be closed after using it (a Ressource) can be used with try-with-ressource (like Connection for example). You don't have to take care of closing it manually (in an finally block for example).
So yes, your idea is right:
try/catch for Class.forName("org.apache.hive.jdbc.HiveDriver"); - because this is not AutoCloseable
try-with-ressource for Connection con = DriverManager.getConnection(connectionUri, userName, password);
Statement stmt = con.createStatement();- because Connection and Statement implement AutoCloseable
Reference:
https://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html
When you're using Java 6 or better and the Apache Hive JDBC driver is JDBC 4 compliant or better* then you do not need the Class.forName("org.apache.hive.jdbc.HiveDriver") stuff at all.
Therefore you can just remove the entire try/catch block from your second solution and you're good to go with just:
try (Connection con = DriverManager.getConnection(connectionUri, userName, password);
Statement stmt = con.createStatement()) {
stmt.executeUpdate(query);
} catch (SQLException e) {
e.printStackTrace();
}
* Which is the case for version 1.2.0 or newer of the Hive JDBC driver
Related
In the below example we are closing connection and prepared statement using try with resource. It will close connection and prepared statement.
And also we are using 2 try block as explained below
For closing connection and prepared statement
Closing result set
In future, if we have any file-related operation then we'll need to write another try with resource block
try (Connection con = ds.getConnection();
PreparedStatement ps = con.prepareStatement(sql);) {
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
list.add(rs.getInt("id"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
But if we are not using try with resource then we can rewrite above login in single try catch block as below
try {
Connection con = ds.getConnection();
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
list.add(rs.getInt("id"));
}
} catch (Exception e) {
// Closing RS
// Closing PS
// Closing Connection or Customized closing connection logic
}
Question: Even if we have any custom operation while closing connection, is it possible to use a try with resource block?
Also please suggest which one better solution in that case.
Try with resources is a better solution because it uses your connections only inside the "try" block. BUT :
catch (SQLException e)
is not the same thing with :
catch (Exception e)
The (Exception e) will catch SQLException and if you said that you want to do some file related operations, will catch maybe a FileNotFoundException or IOException too so this catch is not very suggestive. In my opinion you should first read the Single Responsibility Principle and then you'll see that the best option to handle your problem is to create 2 try blocks which will handle independently the operations like this:
public static List<Integer> getAllProducts() {
List<Integer> productIds = new ArrayList<>();
try (Connection con = ds.getConnection(); PreparedStatement ps = con.prepareStatement(sql);) {
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
productIds.add(rs.getInt("id"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return productIds;
}
public static void writeSomething(String fileName) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
writer.write("StackOverflow");
} catch (IOException e) {
e.printStackTrace();
}
}
I've had a similar issue a couple of weeks ago. You don't need to have multiple try-with-resources, you can only have one see this.
But in your second sample of code, you don't want to close your connection and all in the catch block. You must use the finally block.
In short you can use only one try-with-resources for the "normal" stuff, and create another try-catch-finally inside the latter (or use call to a custom method) to handle and close your customs operations.
try (Connection conn = datasource.getConnection();
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery(request); ) {
while (rs.next())
{
// Do your stuff.
}
try
{
// Do your stuff.
} catch (Whatever e) {
// Handle.
} finally {
// Close your custom stuff.
}
} catch (SQLException ex) {
// throw something.
}
Hope this helps.
I am trying to see the vulnerability of my code with fortify. The report said that I have an issue which said "the function sometimes fails to release a database resource allocated by". Here is the code and in which line the issue pointed. I've tried to close the connection in the finally block but it not solve the issue. How to fix this?
private AnotherService anotherService;
private void create() {
Connection conn = null;
try {
conn = getCon(); // With fortify, there's an issue which said "the function sometimes fails to release a database resource allocated by", and it refers to this line
conn.setAutoCommit(false);
anotherService.myFunction(conn);
// the conn.commit() is inside anotherService, because I have to make one connection
// rest of code
} catch (Exception e) {
e.printStackTrace;
if (null != conn) {
conn.rollback();
}
} finally {
if (null != conn) {
conn.close();
}
}
}
private static Connection getCon() {
Connection connection = null;
try {
Class.forName("org.postgresql.Driver");
connection = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/dbname",
"username",
"password");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
Addition:
If I use try-with-resource (like this try (Connection conn = getCon()), to automatically close things, how I could call conn.rollback() in the catch block if any exception occured? Since the conn variable declared inside the try-with-resources.
Well, I solve my problem, the close method should call inside try-catch in the finally block, as mentioned in this link.
In case the link broken, here is the code that I use to solve my problem:
Statement stmt = null;
ResultSet rs = null;
Connection conn = getConnection();
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(sqlQuery);
processResults(rs);
} catch (SQLException e) {
// Forward to handler
} finally {
try {
if (rs != null) {rs.close();}
} catch (SQLException e) {
// Forward to handler
} finally {
try {
if (stmt != null) {stmt.close();}
} catch (SQLException e) {
// Forward to handler
} finally {
try {
if (conn != null) {conn.close();}
} catch (SQLException e) {
// Forward to handler
}
}
}
}
i'm running this method to update an SQL using DBCP connection pooling:
After exactly 8 times, the method setValue stops doing so, and no data is sent.
public static void setValue(String user, Integer id){
Connection connection = null;
try {
try {
connection = DataSource.getInstance().getConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
ttl++;
PreparedStatement ps = connection.prepareStatement("REPLACE INTO " + "accounts"+ " (user,id) VALUES(?,?)");
ps.setString(1, user);
ps.setInt(2, id);
ps.executeUpdate();
ps.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
return;
}
I am not familiar with MySQL or connection pooling, i do not know what is going wrong here. Please help me troubleshoot this or provide any suggestions? Thank you so much!
Yes, you should be closing your connection, which will simply return it to the pool. Basically you should add this in a finally {} block in your method. Hope this helps.
public static void setValue(String user, Integer id){
Connection connection = null;
try {
try {
connection = DataSource.getInstance().getConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
ttl++;
PreparedStatement ps = connection.prepareStatement("REPLACE INTO " + "accounts"+ " (user,id) VALUES(?,?)");
ps.setString(1, user);
ps.setInt(2, id);
ps.executeUpdate();
ps.close();
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
if (connection != null) connection.close();
}
return;
}
My guess is that you are just using all the connections in your pool
try putting in a finally block
finally {
connection.close();
}
Even though you are using a connection pool you still have to close the connection - it's just that the connection pool doesn't actually close it, it just returns it to the pool so someone else can use it.
Use a try catch finally block, commit your connection in the try, close your prepared statement in the finally, and on exception rollback.
public static void setValue(String user, Integer id){
Connection connection = null;
try {
try {
connection = DataSource.getInstance().getConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (PropertyVetoException e) {
e.printStackTrace();
}
ttl++;
PreparedStatement ps = connection.prepareStatement("REPLACE INTO " + "accounts"+ " (user,id) VALUES(?,?)");
ps.setString(1, user);
ps.setInt(2, id);
ps.executeUpdate();
connection.commit();
} catch (SQLException ex) {
connection.rollback();
ex.printStackTrace();
}
finally {
ps.close();
}
return;
}
I found this code in a tutorial but it isn't working when I debug it try the connection and then it isn't throw exception only go to the finally block without do any line of code under the DriverManager.getConnection().
Why? Anyone has an idea?
Connection con = null;
Statement st = null;
ResultSet rs = null;
String url = "jdbc:mysql://host/databasename";
String user = "user";
String password = "pass";
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
con = (Connection) DriverManager.getConnection(url, user, password);
st = (Statement) con.createStatement();
rs = st.executeQuery("SELECT * FROM Message");
if (rs.next()) {
System.out.println(rs.getString(1));
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Version.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
} catch (java.sql.SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Version.class.getName());
lgr.log(Level.WARNING, ex.getMessage(), ex);
} catch (java.sql.SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Logcat write this:
Logcat Message
1) DriverManager.getConnection() returns an object of type Connection, so there is no need to cast it. Same thing for st = (Statement) con.createStatement();
2) Unless you're running MySQL on a remote machine, you need to make sure you have MySQL installed on your local machine. If you decide to run MySQL on your local machine, you can connect to it with String url = "jdbc:mysql://localhost/{existing_db_name}"; given that everything else remains the same.
3) It seems like you're catching the same exception twice:
try{
con = (Connection) DriverManager.getConnection(url, user, password);
...
}catch (SQLException ex) {
Logger lgr = Logger.getLogger(Version.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
} catch (java.sql.SQLException e) {
e.printStackTrace();
}
As a result, your second catch block, the one that prints the exception message to System.err, never runs. Instead, you print the exception message to a Logger. This might be why you think no exception is being thrown, when in reality, an exception is being thrown.
4) Make sure you download the JDBC driver for MySQL. Copy and paste it into the directory of your project.
I've deleted some catch block:
Connection con = null;
Statement st = null;
ResultSet rs = null;
String url = "jdbc:mysql://host:3306/databasename";
String user = "user";
String password = "pass";
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
con = (Connection) DriverManager.getConnection(url, user, password);
st = (Statement) con.createStatement();
rs = st.executeQuery("SELECT * FROM Message");
if (rs.next()) {
System.out.println(rs.getString(1));
}
} catch (SQLException ex) {
ex.printStackTrace();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
finally {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (con != null) {
con.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
Can you please specify what String url are you using? At this point, with these modifications I obviously get a SQLException with No suitable driver found for jdbc:mysql://host/databasename
I need a good way to close SQLIte connections in Java. After a few suggestion by other users I decided to add to my code a finally block to be sure that closing operation are always executed.
public static boolean executeQuery(String query)
{
Connection conn = null;
Statement stmt = null;
try
{
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection(Global.dbPath);
stmt = conn.createStatement();
stmt.execute(query);
return true;
}
catch(ClassNotFoundException e)
{
System.out.println(e);
return false;
}
catch(SQLException e)
{
System.out.println(e);
return false;
}
finally
{
try
{
stmt.close();
conn.close();
return true;
}
catch (SQLException ex)
{
System.out.println ("Errore closing connections");
return false;
}
}
}
I'm not sure that this is the best solution.
How can I optimize this for readability?
A few comments; nutshells:
Separate the SQL exceptions from the reflection exception.
Are your SQL exceptions recoverable? If not, throw an app-specific RuntimeException.
Wrap up the connection and statement close exceptions in a utility method, yours or a 3rd party's.
Don't short-change exception handling; dump the stack trace.
This leads to the following:
public static boolean executeQuery(String query) {
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
throw new DbException("Could not find JDBC driver", e);
}
Connection conn = null;
Statement stmt = null;
try {
conn = DriverManager.getConnection(Global.dbPath);
stmt = conn.createStatement();
stmt.execute(query);
return true;
} catch(SQLException e) {
throw new DbException("Exception during statement execution", e);
} finally {
DbUtils.closeQuietly(conn);
DbUtils.closeQuietly(stmt);
}
}
(I'm using Apache Commons' DbUtils for its closeQuietly, it checks for null (yours didn't). Your own version might throw an app-specific exception as I do here with DbException. This wraps up all your DB-related exceptions into a single exception class, which may or may not be what you need.
If you want to make sure a command is executed you have to put it alone into a try catch block:
try {
stmt.close();
}
catch (Exception ex) {
}
try {
conn.close();
}
catch (Exception ex) {
System.out.println ("Error closing connections");
return false;
}