The correct way to get/close DataSource connection - java

I am developing a dynamic web project on eclipse.
Below is an example of connecting MySQL using DataSource.
Is it the correct way? I mean is it normal to get connection in a Servlet?
Moreover, I find this way to get/close connection is tedious because I need to write exact same part of codes every time when I want to get/close connection. I think there should be a better way. Could someone give me some suggestions?
Thank you!
#WebServlet(name="HelloUser", urlPatterns={"/hellouser"})
public class HelloUserServlet extends HttpServlet{
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
DataSource ds = MyDataSourceFactory.getMySQLDataSource();
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
con = ds.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery(...);
...
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}

Starting from Java 7 you can use try-with-resource( JDBC api is updated to implement Autocloseable) .
The try-with-resources statement is a try statement that declares one
or more resources. A resource is an object that must be closed after
the program is finished with it
E.g.
try (Connection con = ds.getConnection();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(...)) {...}

Related

Trying to show info from database into terminal

I'm trying to display a list of the names of people in the database from the terminal, but not sure about how I would go about this. Right now I'm using a prepared statement
public static void showNames() throws SQLException {
Statement stmt=null;
Connection conn=null;
try {
conn = DriverManager.getConnection(DB_URL, USER, PASS);
stmt = conn.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
String selectTable="SELECT * FROM userInfo;";
stmt.execute(selectTable);
}
You're close.
Below code is not a complete answer, but hopefully enough to get you moving in the direction of obtaining a complete answer. The below code is basically the code you posted with some modifications.
public static void showNames() throws SQLException {
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
String selectTable="SELECT * FROM userInfo;";
try {
conn = DriverManager.getConnection(DB_URL, USER, PASS);
stmt = conn.createStatement();
rs = stmt.executeQuery(selectTable);
while (rs.next()) {
Object obj = rs.getObject("name of column in database table USERINFO");
System.out.println(obj);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
}
You didn't post the structure of database table USERINFO, so replace name of column in database table with the actual column name.
By the way, there are many examples of how to do this on the Internet, for example Processing SQL Statements with JDBC.

Closing Connection, PreparedStatement, and ResultSet all in one call

Is there anything wrong in closing my connection resources like this? I seem to still have idle connections in postgres running.
public void doSomething(){
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
con = getConnection();
ps = con.prepareStatement("sql here");
....
rs = ps.executeQuery();
...
} catch(Exceptions stuff){
} finally {
closeAll(con,ps,rs);
}
}
public void closeAll(Connection con, PreparedStatement ps, ResultSet rs){
try{
if(rs != null){
rs.close();
}
if(ps != null){
ps.close();
}
if(con != null){
con.close();
}
} catch(SQLException e){
....
}
}
Practice the Best Practice
Yes, their is a problem in closing connection the way you have closed.
Suppose, an exception occurred while closing ResultSet object the rest things would not be closed
Second, suppose if everything goes fine, still you are holding other connection (etc) you are not using, it adds to the burden to the JVM, Database, Memory manager etc
It is recommended to use " try(){} with resource " feature available in JAVA 7 or if you are using JAVA 6 close them when it is no longer needed.

Try-with-resources equivalent in Java 1.6

I have the following code:
public class Main {
public static void main(String[] args) throws SQLException {
try (
Connection conn = DBUtil.getConnection(DBType.HSQLDB);
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("SELECT * FROM tours");
) {
DBUtil.getConnection();
} catch (SQLException e) {
DBUtil.processException(e);
}
}
}
I use this code to fetch data from a database. My problem is that I'm not allowed to use the Java 1.7 compiler and have to use 1.6.
How can I translate the try-with-resources-code to use with a 1.6 compiler?
What exactly happens in this special try block?
Oracle explains how try-with-resources works here
The TL;DR of it is:
There is no simple way of doing this in Java 1.6. The problem is the absence of the Suppressed field in Exception. You can either ignore that and hardcode what happens when both try AND close throw different exceptions, or create your own Exception sub-hierarchy that has the suppressed field.
In the second case, the link above gives the proper way of doing it:
AutoClose autoClose = new AutoClose();
MyException myException = null;
try {
autoClose.work();
} catch (MyException e) {
myException = e;
throw e;
} finally {
if (myException != null) {
try {
autoClose.close();
} catch (Throwable t) {
myException.addSuppressed(t);
}
} else {
autoClose.close();
}
}
is equivalent to
try (AutoClose autoClose = new AutoClose()) {
autoClose.work();
}
In case you want to make it easier and not create a whole lot of new Exception classes, you will have to decide what to throw in the catch clause inside the finally (t or e).
PS. Dealing with multiple variable declaration in the try is also discussed in the link above. And the amount of code that you need to do it properly is staggering. Most people take shortcuts in Java 1.6 by not coping with exceptions in the finally block and using nullchecks.
I would advise usage of apache's commons-dbutils library which have class DBUtils with close and closeQuietly methods.
The code would look like this:
import org.apache.commons.dbutils.DBUtils;
...
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = myOwnUtil.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery( "SELECT * FROM table" ); // or any other custom query
} catch ( SQLException e ) {
<<handle exception here>>;
} finally {
DBUtils.closeQuietly( conn );
DBUtils.closeQuietly( stmt );
DBUtils.closeQuietly( rs );
// or simply use DBUtils.close( conn, stmt, rs );
}
Note that closeQuietly will throw no exceptions, while close might cast SQLException, so adapt the code to your own use case.
If you want to close streams than you can use apache's commons-io with IOUtils class which also have close and closeQuietly.
Do it like this:
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection(DBType.HSQLDB);
stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery("SELECT * FROM tours");
} catch (SQLException e) {
DBUtil.processException(e);
} finally {
if(conn != null) {
conn.close();
}
if(stmt != null) {
stmt.close();
}
if(rs != null) {
rs.close();
}
}

Handling all exceptions when executing SQL in Java

There are many steps involved in executing one SQL statement in Java:
Create connection
Create statement
Execute statement, create resultset
Close resultset
Close statement
Close connection
At each of these steps SQLException can be thrown. If we to handle all exception and release all the resources correctly, the code will will look like this with 4 levels of TRY stacked on the top of each other.
try {
Connection connection = dataSource.getConnection();
try {
PreparedStatement statement = connection.prepareStatement("SELECT 1 FROM myTable");
try {
ResultSet result = statement.executeQuery();
try {
if (result.next()) {
Integer theOne = result.getInt(1);
}
}
finally {
result.close();
}
}
finally {
statement.close();
}
}
finally {
connection.close();
}
}
catch (SQLException e) {
// Handle exception
}
Can you propose a better (shorter) way to execute a statement while still release all the consumed resources?
If you are using Java 7, the try with resources statement will shorten this quite a bit, and make it more maintainable:
try (Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement(queryString); ResultSet rs = ps.execute()) {
} catch (SQLException e) {
//Log the error somehow
}
Note that closing the connection closes all associated Statements and ResultSets.
Check out Apache Commons DbUtils, and in particular the closeQuietly() method. It will handle the connection/statement/result set closing correctly, including the cases where one or more are null.
An alternative is Spring JdbcTemplate, which abstracts a lot of work away from you, and you handle your database queries in a much more functional fashion. You simply provide a class as a callback to be called on for every row of a ResultSet. It'll handle iteration, exception handling and the correct closing of resources.
I create a utility class with static methods I can call:
package persistence;
// add imports.
public final class DatabaseUtils {
// similar for the others Connection and Statement
public static void close(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (Exception e) {
LOGGER.error("Failed to close ResultSet", e);
}
}
}
So your code would be:
Integer theOne = null;
Connection connection = null;
PreparedStatement statment = null;
ResultSet result = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
while (result.next()) {
theOne = result.getInt(1);
}
} catch (SQLException e) {
// do something
} finally {
DatabaseUtils.close(result);
DatabaseUtils.close(statement);
DatabaseUtils.close(connection);
}
return theOne;
I'd recommend instantiating the Connection outside this method and passing it in. You can handle transactions better that way.
Connection connection = null;
PreparedStatement statement = null;
ResultSet result = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
if (result.next()) {
Integer theOne = result.getInt(1);
}
}
catch (SQLException e) { /* log error */ }
finally {
if (result != null) try { result.close(); } catch (Exception e) {/*log error or ignore*/}
if (statement != null) try { statement.close(); } catch (Exception e) {/*log error or ignore*/}
if (connection != null) try { connection.close(); } catch (Exception e) {/*log error or ignore*/}
}
Just close the Connection, this releases all resources*. You don't need to close Statement and ResultSet.
*just make sure you don't have any active transactions.
Your code can be shortened and written in this way...
Connection connection = dataSource.getConnection();
PreparedStatement statement = null;
ResultSet result = null;
try {
statement= connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
if (result.next()) {
Integer theOne = result.getInt(1);
}
} catch (SQLException e) {
// Handle exception
} finally {
if(result != null) result.close();
if(statement != null) statement.close();
if(connection != null) connection.close();
}

Java Servlet DB Query with Ajax - slow query time and querystring not always fully passed to the servlet

I'm trying to create a AJAX based SQL query with Java EE and Servlets. I'm using Glassfish 3.01 and MS SQL server with Jquery on the client side.
I put everything together, and bind my ajax function to the textfield's onkeyup event. But sometimes When I put 'teststring' into the textbox only "teststrin" passed to the Servlet. So basically the last char disappears and therefore the query result is not correct.
Not to mention when the resultset contains large amount of data the query is pretty slow. Could you please check if I'm doing something wrong on the server and client side?
On the client side I have this JQuery function:
function ajaxSearch(sstring) {
if (sstring.length < 3)
{
$("#external").html("at least 3 chars please....")
}
else
{
$('#loading').ajaxStart(function() {
$(this).show()
$("#external").hide()
});
$('#loading').ajaxComplete(function() {
$(this).hide()
$("#external").show()
});
$.ajax({
type:"GET",
url: "/myApp/getStd",
dataType: "application/x-www-form-urlencoded",
data: "sstring="+escape(sstring),
async: true,
success: function(data){
$("#external").html(data);
}
})
}
}
On the server side I have this:
#WebServlet(name="getStd", urlPatterns={"/getStd"})
public class getStd extends HttpServlet {
#Override
public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
ArrayList rows = new ArrayList();
res.setCharacterEncoding("UTF-8");
res.setContentType("text/html");
PrintWriter out = res.getWriter();
String sql=null;
String test= req.getParameter("sstring");
try{
InitialContext cxt = new InitialContext();
if (cxt == null) {
throw new Exception("Uh oh -- no context!");}
DataSource ds = (DataSource) cxt.lookup( "jdbc/Sample" );
conn = ds.getConnection();
stmt = conn.createStatement();
sql="Select * from MYDB.dbo.testdb where myField like '%"+req.getParameter("sstring")+"%';";
rs = stmt.executeQuery(sql);
while(rs.next()){
stdRecord cols = new stdRecord();
cols.setTeljel(rs.getString("Field1"));
cols.setTitle(rs.getString("Field2"));
cols.setICS(rs.getString("Field3"));
cols.setREF(rs.getString("Field4"));
rows.add(cols);
}
req.setAttribute("std", rows);
req.setAttribute("query",test );
req.getRequestDispatcher("/showRes.jsp").forward(req, res);
// close everything to free up resources
rs.close();
rs = null;
stmt.close();
stmt = null;
conn.close(); /
conn = null;
rows=null;
} catch (SQLException e) {
e.printStackTrace(out);
} catch (Exception e) {
e.printStackTrace(out);
} finally {
if (rs != null) {
try { rs.close(); } catch (SQLException e) { ; }
rs = null;
}
if (stmt != null) {
try { stmt.close(); } catch (SQLException e) { ; }
stmt = null;
}
if (conn != null) {
try { conn.close(); } catch (SQLException e) { ; }
conn = null;
}
}
}
}
Thanks in advance.
As to the lag in keyup, I think this is related to the performance issue, so let's fix that first and then review afterwards.
As to the performance, you've given very little information about your setup, but two common solutions which are often overlooked by starters are the following:
Use a connection pooled DataSource instead of DriverManager. This saves the cost of connecting the DB on every query (which can take over 200ms while a pooled connection is returned in no-time). Consult the JNDI resource config documentation of the application server in question for details (hint: admin console).
Limit the resultset size in SQL side instead of in Java side. This saves the cost of transferring irrelevant data over network. Just return the top 10 results or something instead of the entire table. Consult the SQL manual of the database in question for details (hint: SET ROWCOUNT).

Categories