H2 in memory database multiple connections to same database - java

I am using h2 in memory database for testing. I have a situation where nested database calls will happen. Using h2 the connection is getting closed on the nested call, even if the objects are different.
ClassA:
Public class TestDb {
Public String getById(String id) {
try {
Connection conn= getConnection();
PreparedStatement ps = conn.prepareStatement(“query”);
ResultEntity rs = ps.executeQuery();
getOthersById(rs.get(id));
//here rs is closed and seering error as: object is closed
rs.get(2);
}Catch(Exception ex) {
//handle exceptions
}finally {
// close resultset
//close ps
// close conn
}
}
public int getOthersById(String id) {
try {
//get new connection
Connection conn= getConnection();
PreparedStatement ps = conn.prepareStatement(“query”);
ResultEntity rs = ps.executeQuery();
rs.get(id);
}Catch(Exception ex) {
//handle exceptions
}finally {
// close resultset
//close ps
// close conn
}
}
}
The problem in h2 is after the closing new connection and result set in getOthersById method, resultSet in getById is closed.
I am creating the h2 as below:
jdbc:h2:mem:test;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;

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.

What is a proper way to connect to a sqlite database, execute a prepared Statement and close the connection with java?

This is my code at the moment. I have or had several problems:
Database is busy - error
SQL error or missing database
Resultset closed
Which code structure should I use if I want to prevent both of these errors?
Do I need to connect in the try block? Where do I need to close the connection? Where do I need to close the preparedStatement?
I was not able to find a solution by connecting the information of different pages by myself until now.
public boolean checkForUser(String username){
try(Connection con = this.connect();
PreparedStatement pstmt = createPreparedStatementRegistrate(conn, username);
ResultSet rs= pstmt.executeQuery();)
{
if (rueck.next()){
pstmt.close();
rs.close();
con.close();
//do some stuff
}
}catch(SQLException e){
e.printStackTrace();
}
return null;
}
private PreparedStatement createPreparedStatementRegistrate(Connection conn, String username) throws SQLException {
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
return pstmt;
}
private Connection connect() {
String url = "jdbc:sqlite:user.db";
Connection con = null;
try {
con = DriverManager.getConnection(url);
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
java.sql.SQLException: ResultSet closed
at org.sqlite.core.CoreResultSet.checkOpen(CoreResultSet.java:69)
at org.sqlite.jdbc3.JDBC3ResultSet.findColumn(JDBC3ResultSet.java:38)
at org.sqlite.jdbc3.JDBC3ResultSet.getString(JDBC3ResultSet.java:443)
at zugriffsverwaltung.Zugriffsverwaltung.loeschen(Zugriffsverwaltung.java:215)
at zugriffsverwaltung.Zugriffsverwaltung.<init>(Zugriffsverwaltung.java:37)
at main.Server.<init>(Server.java:29)
at main.Server.main(Server.java:46)
org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (Connection is closed)
at org.sqlite.core.DB.newSQLException(DB.java:909)
at org.sqlite.core.CoreStatement.internalClose(CoreStatement.java:115)
at org.sqlite.jdbc3.JDBC3Statement.close(JDBC3Statement.java:35)
at org.sqlite.jdbc4.JDBC4Statement.close(JDBC4Statement.java:27)
at zugriffsverwaltung.Zugriffsverwaltung.loeschen(Zugriffsverwaltung.java:238)
at zugriffsverwaltung.Zugriffsverwaltung.<init>(Zugriffsverwaltung.java:37)
at main.Server.<init>(Server.java:29)
at main.Server.main(Server.java:46)
The problem is that you are closing the result set, statement and connection before you do things with the result set. This is not allowed: a result set needs to be open when you retrieve values using getString (not shown in your code, but present in your stack trace).
As you are using try-with-resource which will close the resource on exit, it is even unnecessary to explicitly close. It also looks like the SQLite driver does not meet the JDBC requirements that closing an already closed resource should be a no-op, as it is throwing an exception that the connection is closed when closing the statement (likely by the try-with-resources).
You need to change your code to
public boolean checkForUser(String username){
try(Connection con = this.connect();
PreparedStatement pstmt = createPreparedStatementRegistrate(conn, username);
ResultSet rs= pstmt.executeQuery();)
{
if (rueck.next()){
//do some stuff
}
}catch(SQLException e){
e.printStackTrace();
}
return null;
}
That is, remove the lines
pstmt.close();
rs.close();
con.close();

Operation not allowed after ResultSet closed. Reasons

What I did wrong? I tried to swap rs.close(), pstmt.close(), conn.close().
I created a PreparedStatement.
But I still can not display the contents of a database table. If I remove conn.close(), everything works! How close the connection and get an output on the jsp?
This is my code:
public ResultSet executeFetchQuery(String sql) {
ResultSet rs = null;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = Database.getConnection();
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
try {
rs.close();
pstmt.close();
conn.close();
} catch (SQLException ex) {
Logger.getLogger(PhoneDAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
return rs;
}
public ArrayList<Phone> getAllPhone() {
ArrayList<Phone> list = new ArrayList<>();
String sql = "SELECT * FROM phones.product;";
ResultSet rs = executeFetchQuery(sql);
try {
while (rs.next()) {
Phone phone = new Phone();
phone.setId(rs.getInt("id"));
phone.setName(rs.getString("name"));
phone.setPrice(rs.getInt("price"));
phone.setQuantity(rs.getInt("quantity"));
phone.setDescription(rs.getString("description"));
System.err.println(phone);
list.add(phone);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
return list;
}
ResultSet rs = executeFetchQuery(sql);
The above statement closes everything.
Actually your code should be
DBConnection
Iterate through result set
Store the values/display the value directly(depends on your need)
Finally close the connection.
Which is the proper way to access the data from db.
The more common pattern for this kind of process is to maintain the connection and the statement outside the main query code. This is priomarily because connections would generally be allocated from a pool as they are expensive to create and preparing the same statement more than once is wasteful.
Something like this is most likely to work both efficiently and correctly.
static final Connection conn = Database.getConnection();
static final String sql = "SELECT * FROM phones.product;";
static final PreparedStatement pstmt = conn.prepareStatement(sql);
public ArrayList<Phone> getAllPhone() {
ArrayList<Phone> list = new ArrayList<>();
ResultSet rs = pstmt.executeQuery();
try {
while (rs.next()) {
Phone phone = new Phone();
phone.setId(rs.getInt("id"));
phone.setName(rs.getString("name"));
phone.setPrice(rs.getInt("price"));
phone.setQuantity(rs.getInt("quantity"));
phone.setDescription(rs.getString("description"));
System.err.println(phone);
list.add(phone);
}
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
rs.close();
}
return list;
}
Note how the ResultSet is closed in a finally block to stop leaks.
There are variations of this pattern which, for example, only create the connection and prepare the statement at the last minute rather than as static final fields like I have here.

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.

Which should I close first, the PreparedStatement or the Connection?

When using a PreparedStatement in JDBC, should I close the PreparedStatement first or the Connection first? I just saw a code sample in which the Connection is closed first, but it seems to me more logical to close the PreparedStatement first.
Is there a standard, accepted way to do this? Does it matter? Does closing the Connection also cause the PreparedStatement to be closed, since the PreparedStatement is directly related to the Connection object?
The statement. I would expect you to close (in order)
the result set
the statement
the connection
(and check for nulls along the way!)
i.e. close in reverse order to the opening sequence.
If you use Spring JdbcTemplate (or similar) then that will look after this for you. Alternatively you can use Apache Commons DbUtils and DbUtils.close() or DbUtils.closeQuietly().
The following procedures should be done (in order)
The ResultSet
The PreparedStatement
The Connection.
Also, it's advisable to close all JDBC related objects in the finally close to guarantee closure.
//Do the following when dealing with JDBC. This is how I've implemented my JDBC transactions through DAO....
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = ....
ps = conn.prepareStatement(...);
//Populate PreparedStatement
rs = ps.executeQuery();
} catch (/*All relevant exceptions such as SQLException*/Exception e) {
logger.error("Damn, stupid exception: " , e);
} finally {
if (rs != null) {
try {
rs.close();
rs = null;
} catch (SQLException e) {
logger.error(e.getMessage(), e.fillInStackTrace());
}
}
if (ps != null) {
try {
ps.close();
ps = null;
} catch (SQLException e) {
logger.error(e.getMessage(), e.fillInStackTrace());
}
}
try {
if (conn!= null && !conn.isClosed()){
if (!conn.getAutoCommit()) {
conn.commit();
conn.setAutoCommit(true);
}
conn.close();
conn= null;
}
} catch (SQLException sqle) {
logger.error(sqle.getMessage(), sqle.fillInStackTrace());
}
}
You can see I've checked if my objects are null and for connection, check first if the connection is not autocommited. Many people fail to check it and realise that the transaction hasn't been committed to DB.

Categories