executor = Executors.newScheduledThreadPool(1);
Runnable helloRunnable = new Runnable() {
public void run() {
controller2.GetAIntFromDatabase(columblName);
}
};
executor.scheduleAtFixedRate(helloRunnable, 0, 10, TimeUnit.MILLISECONDS);
this part of the program generates the increasing heap memory error.
controller2.GetAIntFromDatabase(columblName);
with this function I read an int value from my database.
#Override
public int GetAIntFromDatabase(String columblName) {
int stare = 0;
try{
String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
PreparedStatement preparedStatement = this.connnection.prepareStatement(query);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()){
stare = resultSet.getInt(columblName);
preparedStatement.close();
resultSet.close();
return stare;
}
preparedStatement.close();
resultSet.close();
}catch (SQLException ex) {
System.out.println("GetUtilajStare Error: " + ex);
return 0;
}
return 0;
}
That's the Java heap memory usage after 10 minutes of running:
Why does my heap memory keep increasing?
If an exception is thrown after opening the preparedStatement and the resultSet, they will never be closed. Therefore you should use the finally block which will always be executed.
public int GetAIntFromDatabase(String columblName) {
int stare = 0;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
preparedStatement = this.connnection.prepareStatement(query);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
stare = resultSet.getInt(columblName);
return stare;
}
} catch (SQLException ex) {
System.out.println("GetUtilajStare Error: " + ex);
return 0;
} finally {
if (preparedStatement != null)
preparedStatement.close();
if (resultSet != null)
resultSet.close();
}
return 0;
}
You should use a Java 7+ way of closing the resources, try-with-resources.
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. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements AutoCloseable, which includes all objects which implement Closeable, can be used as a resource.
public int GetAIntFromDatabase(String columblName) {
final String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
try (final PreparedStatement preparedStatement = this.connnection.prepareStatement(query)) {
final ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
return resultSet.getInt(columblName);
}
return 0;
} catch (SQLException ex) {
// Do something better than System.out.println(...)
return 0;
}
return 0;
}
Also you do not have to explicitly close the result set, the prepared statement does it as it owns the result set:
When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
However, if you want to be paranoid and overkill it, as #MarkRotteveel suggests in his comment, you may add as an AutoCloseable resource also the ResultSet, and the code would then look like this:
public int GetAIntFromDatabase(String columblName) {
final String query = "SELECT * FROM stari ORDER BY id DESC LIMIT 1";
try (final PreparedStatement preparedStatement = this.connnection.prepareStatement(query);
final ResultSet resultSet = preparedStatement.executeQuery()
) {
...
}
I have never done it and never needed it and the documentation explicitly states that it's not necessary, but some people have experienced problems in certain edge cases.
In this second case it's especially visible how much the try-with-resources saves you from - you do not need to assign the variables to null, you do not have to check if any of them have been opened, and even if one of the close() methods throws an exception, the "closing chain" is not broken and the close() methods of the other resources are called in any case.
Related
Eclipse IDE always shows following warning:
Resource leak: 'rset' is not closed at this location
But for me the code seems to be correct:
Statement stmt = null;
ResultSet rset = null;
try {
stmt = connection.createStatement();
try {
String query = foo();
rset = stmt.executeQuery(query);
} catch (Exception e) {
String query = bar();
rset = stmt.executeQuery(query);
}
return JsonHandler.resultSetToJson(rset);
} finally {
if (rset != null)
rset.close();
if (stmt != null)
stmt.close();
}
How do I close the ResultSet?
As commented, your second assignment of rset would let the first ResultSet object become a candidate for garbage collection without being closed. Thus the warning from the compiler or your IDE.
To more reliably and clearly close your resources, use try-with-resources.
try-with-resources syntax
Modern Java offers the try-with-resources syntax feature to automatically close any object that implements AutoCloseable with its single method close. The resources will be closed in the reverse of the order in which they were instantiated. And they are closed whether your code completes successfully or throws an exception.
See The Java Tutorials provided free of cost by Oracle Corp.
Try-with-resources is one of my favorite features in Java. Along with text blocks, database work is much easier now, and more fool-proof.
Connnection, Statement, and ResultSet are all such auto-closeable resources. So wrap them in try-with-resource syntax.
Exceptions
Get specific with your exceptions. Trap for the ones expected within the local context.
Code
Here is some untested code.
Notice how we name each ResultSet object differently.
Notice how the nesting of try-with-resources calls communicates visually the cascading structure of our logic.
try
(
Connection conn = myDataSource.getConnection() ;
Statement stmt = conn.createStatement() ;
)
{
try
(
ResultSet rsetFoo = stmt.executeQuery( foo() );
)
{
return JsonHandler.resultSetToJson( rsetFoo );
}
catch ( SQLException | SQLTimeoutException e)
{
try
(
ResultSet rsetBar = stmt.executeQuery( bar() );
)
{
return JsonHandler.resultSetToJson( rsetBar );
}
}
}
catch ( SQLException e )
{
…
}
catch ( SQLTimeoutException e )
{
…
}
If you had searched before posting, you would have found many existing examples, and much discussion, already posted on Stack Overflow.
Use try-with-resources feature
You can use try-with-resources feature of java 7 it will handle the auto closing of the resources as ResultSet,Statement implements AutoCloseable interface.
like : try (ResultSet rset = stmt.executeQuery(query))
similarly for other resources as well.
Try to put the returnstatement after the finally clause. i think your function is ignoring everything that comes after the return statement.
Try something like :
Statement stmt = null;
ResultSet rset = null;
String parsedResult = null; // String or the object type you want to return.
try {
stmt = connection.createStatement();
try {
String query = foo();
rset = stmt.executeQuery(query);
} catch (Exception e) {
String query = bar();
rset = stmt.executeQuery(query);
}
parsedResult = JsonHandler.resultSetToJson(rset);
} finally {
if (rset != null)
rset.close();
if (stmt != null)
stmt.close();
}
return parsedResult;
The Code:
protected List<Object> getAll(Pair<String, Object> primaryKey, String columnLabel) {
List<Object> objects = new ArrayList<>();
try {
ResultSet resultSet = getRows(primaryKey);
while (resultSet.next()) {
objects.add(resultSet.getObject(columnLabel));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return objects;
}
}
protected ResultSet getRows(Pair<String, Object> primaryKey) {
try (Connection con = DataSource.getConnection();
PreparedStatement pst = con.prepareStatement("SELECT * FROM " + table + " WHERE `" + primaryKey.fst + "` = ?")) {
pst.setObject(1, primaryKey.snd);
return pst.executeQuery();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Error
Table's columns are: id (int) | player(string) | friend(string)
as id is auto increment.
The error pointing to (line 5):
while (resultSet.next()) {
when does ResultSet gets closed?
SQLEmmber#getAll(Pair<String, Object> primaryKey, String columnLabel) gets called in SQLFriends.java
Your method getRows() uses a try-with-resources block that contains the connection and the prepared statement. At the end of the try-with-resources block, this will explicitly close the prepared statement and the connection.
Closing the prepared statement will close the result set (and closing the connection will close any open statements, and therefor also close any open result sets).
As documented in ResultSet:
A ResultSet object is automatically closed when the Statement
object that generated it is closed, re-executed, or used to retrieve
the next result from a sequence of multiple results.
You will need to restructure your code so you only close the connection after you have retrieved all rows from the result set.
I'm tying to get an image from MySQL database and show in a JLabel, but when I execute the query and try to get the bytes from the ResultSet it returns an empty array.
I tested the connection, and it is working, tested the query and its also working.
try {
conn = getConnection();
pst = conn.prepareStatement("select * from imagem where serial_imagem = 123658");
rs = pst.executeQuery()
if (rs.next()) {
image = rs.getBytes("img_imagem");
}
}catch (Exception e) {
e.printStackTrace();
}
The code does not close and thus leaks resources. The somewhat ugly Try-With-Resources syntax ensures closing connection, statement and result set, even on returning/exception.
One could make explicit with Optional whether the image was found in the table or not.
Optional.of also guarantees that the field in the database must not contain an SQL NULL value.
Optional<byte[]> loadImageFromDatabase(String imageM) throws SQLException {
String sql = "select img_imagem from imagem where serial_imagem = ?";
try (Connection conn = getConnection();
PreparedStatement pst = conn.prepareStatement(sql)) {
pst.setString(1, imageM);
try (ResultSet rs = pst.executeQuery()) {
if (rs.next()) {
return Optional.of(rs.getBytes(1)); // ofNullable
} else {
return Optional.empty();
}
}
}
}
Usage:
try {
Optional<byte[]> img = loadImageFromDatabase(jtextField1.getText().trim());
img.ifPresent(image -> {
...
});
} catch (SQLException e) {
There is still to remark that I personally do not often use ResultSet.getBytes, but rather getInputStream. Depends on the image size and creation code.
I am attempting to write a method that selects 2 entries into an employee database and removes them (Based on a salary field), I am currently using a counter to accomplish this, however I tried using setMaxRows() so my result set would only have two entries, thus eliminating the need for the counter. I am using try-with-resources to create my statement and that seems to be causing an issue.
public void downSize(Connection con) {
String sql = "SELECT * FROM " + schemaName + "."+tableName+" WHERE EMPLOYEE_SALARY>200000";
try (
PreparedStatement statement = con.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = statement.executeQuery();
)
{
int counter = 0;
System.out.println("Now pruning workforce...");
while(rs.next() && counter<2) {
String name = rs.getString("EMPLOYEE_NAME");
rs.deleteRow();
counter++;
System.out.println(name+" was laid off.");
}
} catch(Exception e) {
e.printStackTrace();
System.out.print("Sql exception happened");
}
}
i've occours this strange error for the first time in my life, and i don't know what does it means. I've a class that retrieve information from a table on a postgresql database, do some operations and return an arraylist with parsed element:
ResultSet rs = ProduttoreDCS.getProduttori();
System.out.println("Recuperato result set produttori");
ArrayList<String[]> res = new ArrayList<String[]>();
while (rs.next()) {
String[] current = new String[6];
current[0] = Integer.toString(rs.getInt("partita_iva"));
current[1] = rs.getString("nome");
current[2] = rs.getString("cognome");
current[3] = rs.getString("via_sede");
current[4] = rs.getString("citta_sede");
current[5] = rs.getString("provincia_sede");
res.add(current);
current = null;
}
return res;
the error is on "while" line.
public static ResultSet getProduttori() throws ClassNotFoundException, SQLException {
/*
* retrieve all record from produttori table
*/
Connection conn = null;
ResultSet res = null;
Statement stmt = null;
String query = "SELECT * FROM produttore";
conn = ConnectionManager.getConnection();
System.out.println("Connection obtained by ProduttoreDCS class");
stmt = conn.createStatement();
res = stmt.executeQuery(query);
stmt.close();
conn.close();
return res;
}
I've encountered the same problem by running the wrong combination of:
Postgres version;
Hibernate dialect;
postgres jdbc driver;
Updating all to the latest version solved the problem for me.
P.S. I know this is not what OP was asking, but this is the first result in Google when you search for the problem.
when you close the connection object in your getProduttori method, your result set will be automatically closed. when you try to re use it , it will be null.
ResultSet rs = ProduttoreDCS.getProduttori();
= null, as you have closed the connection in getProduttori
method, which will automatically close the resultset
thus, it returns null.
From Connection#close
Releases this Connection object's database and JDBC resources
immediately instead of waiting for them to be automatically released.
applies same when closing the Statement as well.For your code to work don't close Statement and Connection untill you get the rows.
#Baadshah has already shown you the standard way. If you are using java 7+ you can make use of try-with-resource block, which would make your life simpler.
try(Connection conn = gettheconn){
get the statement here
get the result set
perform your ops
}
catch(SQLException ex){
ex.printstacktrace();
}
If you observe, there is no finally block, your connection object will be closed once you exit the try block automatically.you don't have to explicity call Connection#close()
As per Docs
A ResultSet object is automatically closed when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.
You are closed the connection and then you are iterating ,where it is null.Please read the data and then close the connection.
A good practice here is
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn =
stmt = conn.prepareStatement("sql");
rs = stmt.executeQuery();
//DO SOME THING HERE
} catch {
// Error Handling
} finally {
try { if (rs != null) rs.close(); } catch (Exception e) {};
try { if (stmt != null) stmt.close(); } catch (Exception e) {};
try { if (conn != null) conn.close(); } catch (Exception e) {};
}
This is the problem:
stmt.close();
conn.close();
You're closing the connection to the database. You can't do that until you've read the data - otherwise how is the ResultSet going to read it? Maybe it will have read some data in to start with, but it's not meant to be a disconnected object.
In particular, from the docuemntation for ResultSet.close:
Note: A ResultSet object is automatically closed by the Statement object that generated it when that Statement object is closed, re-executed, or is used to retrieve the next result from a sequence of multiple results.
Closing the connection makes the resultSet go away.
A ResultSet is not a container you can use to pass data around in, it's only a wrapper around a cursor. You should run through the resultSet contents and copy them into a data structure, then return the data structure. You are already doing that, but you need to do it before closing the statement and connection.
Change the code to:
public static List<String[]> getProduttori() throws ClassNotFoundException, SQLException {
ArrayList<String[]> res = new ArrayList<String[]>();
/*
* retrieve all record from produttori table
*/
Connection conn = null;
ResultSet rs = null;
Statement stmt = null;
String query = "SELECT * FROM produttore";
conn = ConnectionManager.getConnection();
try {
System.out.println("Connection obtained by ProduttoreDCS class");
stmt = conn.createStatement();
try {
rs = stmt.executeQuery(query);
while (rs.next()) {
String[] current = new String[6];
current[0] = Integer.toString(rs.getInt("partita_iva"));
current[1] = rs.getString("nome");
current[2] = rs.getString("cognome");
current[3] = rs.getString("via_sede");
current[4] = rs.getString("citta_sede");
current[5] = rs.getString("provincia_sede");
res.add(current);
}
return res;
} finally {
try {
stmt.close();
} catch (SQLException e) {
log.error(e);
}
}
} finally {
try {
conn.close();
} catch (SQLException e) {
log.error(e);
}
}
}