I am looking at examples of try-with-resources in Java and I understand the following one:
try (Connection conn = DriverManager.getConnection(url, user, pwd);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);) {
...
}
So, the order of closing is:
rs.close();
stmt.close();
conn.close();
which is perfect because a connection has a statement and a statement has a result set.
However, in the following examples, the order of close I think it is the reverse of the expected:
Example 1:
try (FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr)) {
...
}
The order of closing is:
br.close();
fr.close();
Example 2:
try (FileOutputStream fos = new FileOutputStream("testSer.ser");
ObjectOutputStream oos = new ObjectOutputStream(fs);) {
...
}
The order of closing is:
oos.close();
fos.close();
Are these examples correct? I think the close in those examples should be different because:
In the example 1 a BufferedReader has a FileReader.
In the example 2 an ObjectOutputStream has a FileOutputStream.
The ordering is the same: it's always the reverse of the order in which resources are specified. From JLS:
Resources are closed in the reverse order from that in which they were initialized.
However, if the later-specified resources themselves invoke the close() method of the earlier-specified resources (as is the case with BufferedReader and ObjectOutputStream), it may look like they are not happening in the expected order (and that close() will be invoked multiple times).
I think I wasn't right when I said "a connection has a statement and a statement has a result set". Maybe it's the opposite "a result set has a statement and a statement has a connection" or at least "a result set was created by a statement and a statement was created by a connection".
So I think:
try (Parent parent = new Parent();
Child child = parent.createChild();) {
...
}
Is equivalent to:
try (Parent parent = new Parent();
Child child = new Child(parent);) {
...
}
Related
I have primitive get method for my database. I need to get course by its id and then close connection and statement.
public Course get(int id) throws ClassNotFoundException, SQLException {
try (Connection connection = ConnectionConfig.getDbConnection();
PreparedStatement statement = connection.prepareStatement(GET_COURSE)){
statement.setInt(1, id);
ResultSet course = statement.executeQuery();
course.next();
String result = course.getString(1);
return new Course(id, result);
}
}
I want to do it with try-with-resources. Will it work in this code or auto-closing won't work because of return statement in the block? On the other hand, I don't want to use return outside this block because method can return object with null field. What method form is the most effective and readable in this situation? Thank you in advance, I understand this is quite amateurish question)
Closing the connections code is usually written in finally block
Connection connection = null;
try {
connection = ConnectionConfig.getDbConnection();
//do all the stuff
}
finally{
connection.close()
}
The connection will closed by the try with resources block. The condition for that is that a given class implements AutoCloseable. And that is already the case.
As it can be seen here
In many try-with-resource examples I have searched, Statement and ResultSet are declared separately. As the Java document mentioned, the close methods of resources are called in the opposite order of their creation.
try (Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql) ) {
} catch (Exception e) {
}
But now I have multiple queries in my function.
Can I make Statement and ResultSet in just one line ? My code is like:
try (ResultSet rs = con.createStatement().executeQuery(sql);
ResultSet rs2 = con.createStatement().executeQuery(sql2);
ResultSet rs3 = con.createStatement().executeQuery(sql3)) {
} catch (Exception e) {
}
If I only declare them in one line, does it still close resource of both ResultSet and Statement?
When you have a careful look you will see that the concept is called try-with-resources.
Note the plural! The whole idea is that you can declare one or more resources in that single statement and the jvm guarantees proper handling.
In other words: when resources belong together semantically, it is good practice to declare them together.
Yes, and it works exactly as you put it in your question, multiple statements separated by semicolon.
You may declare one or more resources in a try-with-resources statement. The following example retrieves the names of the files packaged in the zip file zipFileName and creates a text file that contains the names of these files:
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
// Enumerate each entry
for (java.util.Enumeration entries =
zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName =
((java.util.zip.ZipEntry)entries.nextElement()).getName() +
newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
ResultSet implements AutoCloseable, which means try-with-resources will also enforce closing it when it finishes using it.
https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
I am getting null value when I am reading the blob data from database. What might be the issue? Can some one help me on this?
Connection con = null;
PreparedStatement psStmt = null;
ResultSet rs = null;
try {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
con =
DriverManager.getConnection("jdbc:oracle:thin:#MyDatabase:1535:XE","password","password");
System.out.println("connection established"+con);
psStmt = con
.prepareStatement("Select Photo from Person where Firstname=?");
int i = 1;
psStmt.setLong(1, "Nani");
rs = null;
rs = psStmt.executeQuery();
InputStream inputStream = null;
while (rs.next()) {
inputStream = rs.getBinaryStream(1);
//Blob blob = rs.getBlob(1);
//Blob blob1 = (Blob)rs.getObject(1);
//System.out.println("blob length "+blob1);//rs.getString(1);
}
System.out.println("bytessssssss "+inputStream);//here i am getting null value.
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I believe you didn't use setString function to assign any value to firstname which leads to null
for example:
ps.preparedStatement("Select photo from person where firstname = ?");
ps.setString(1,"kick"); <----- add this line
system.out.println("bytes "+rs.getBinaryStream(1));
Another suggestions
there is no need to use rs = null; inside try catch block because you have rs=null; at beginning of
your code.
change
InputStream inputStream = null;
to
InputStream inputStream = new InputStream();
or
get rid of InputStream inputStream = null;
source you should take a look at
The most obvious error is using setLong instead of setString.
However one practice is fatal: declaring in advance. This in other languages is a good practice, but in java one should declare as close as possible.
This reduces scope, by which you would have found the error! Namely inputStream is called after a failed rs.next() - outside the loop. Maybe because no records were found.
This practice, declaring as near as feasible, also helps with try-with-resources which were used here to automatically close the statement and result set.
Connection con = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection(
"jdbc:oracle:thin:#MyDatabase:1535:XE","password","password");
System.out.println("connection established"+con);
try (PreparedStatement psStmt = con.prepareStatement(
"Select Photo from Person where Firstname=?")) {
int i = 1;
psStmt.setString(1, "Nani");
try (ResultSet rs = psStmt.executeQuery()) {
while (rs.next()) {
try (InputStream inputStream = rs.getBinaryStream(1)) {
//Blob blob = rs.getBlob(1);
//Blob blob1 = (Blob)rs.getObject(1);
//System.out.println("blob length "+blob1);//rs.getString(1);
Files.copy(inputStream, Paths.get("C:/photo-" + i + ".jpg"));
}
++i;
}
//ERROR System.out.println("bytessssssss "+inputStream);
} // Closes rs.
} // Closes psStmt.
}
1- In your code when setting the parameter's value of SQL query, be sure to use the appropriate data type of the field. So here you should use
psStmt.setString(1, "Nani");
instead of
psStmt.setLong(1, "Nani");
2- Make sure that the query is correct (Table name, field name).
3- Make sure that the table is containing data.
Here is the scenario, I try to upload a file, and after I uploaded it, I tried to access that file from the new directory (which i just write to), but I received error message:
There was an error opening this document. The file is already open or
in use by another application.
Below is my coding.
try{
conn = this.getConnection();
String getIP = "SELECT IP FROM TABLE WHERE ID='3'";
ps = conn.prepareStatement(getIP);
rs = ps.executeQuery();
Part file = request.getPart("upload");
String fileName = extractFileName(request.getPart("upload"));
String basePath = "//"+ipAdd+"/ns/"+fileName;
File outputFilePath = new File(basePath + fileName);
inputStream = file.getInputStream();
outputStream = new FileOutputStream(outputFilePath);
int read = 0;
final byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
}catch(Exception ex){
ex.printStackTrace();
throw ex;
}finally{
if(!conn.isClosed())conn.close();
if(!ps.isClosed())ps.close();
if(!rs.isClosed())rs.close();
inputStream.close();
outputStream.close();
}
Is it because that I open the file too quick after I start the upload function? I do realize that after 1/2minutes, I'm able to access the file. Is there anyway to solve this bug?
You're not closing the file. Add
outputStream.close();
after the loop.
EDIT And do it first, before closing anything else. You should really use try-with-resources here. If you get any exception closing anything, the other closes won't happen.
In your code above, if an exception occurs whilst closing the JDBC Connection, then none of the other JDBC objects or Streams are closed. The finally block exits at that point.
Since Java 7, closing Streams and JDBC objects (Connections, Statements, ResultSets etc) can be done in a proper exception handling framework nice and easily, since they all implement a common interface AutoCloseable
So you can write a single close() method and handle the exception inside:
public void close(AutoCloseable closeable) {
try {
closeable.close();
} catch (Exception e) {
//Just log the exception. there's not much else you can do, and it probably doesn't
//matter. Don't re-throw!
}
}
So when closing your JDBC objects, you can do this in the finally block:
close(conn);
close(ps);
close(rs);
close(inputStream);
close(outputStream);
Now if an exception occurs whilst closing any of the objects, it is handled and the following objects are still closed.
I created an application that writes data to the database every 5 minutes.
However after some time this error appears:
Error: Data source rejected establishment of connection, message from server: "Too many connections"
I've been searching around and tells you to close the connection to the database after every request side.
I tried this:
conexao.close();
But it gives me this error:
No operations allowed after conection closed.
I apologize if the question is not well formulated.
Thanks for the help
---------------------What I tried but didn't work---------------------------
Add
finally{
if(conexao!=null)
conexao.close();
}
Class.forName("com.mysql.jdbc.Driver");
Connection conexao = (Connection) DriverManager.getConnection("jdbc:mysql://localhost/bdTeste", "root", "root");
Statement stm = conexao.createStatement();
BufferedReader reader = new BufferedReader(new FileReader("C:/Users/RPR1BRG/Desktop/test.txt"));
String dados[] = new String[6];
String linha = reader.readLine();
while (linha != null) {
StringTokenizer st = new StringTokenizer(linha, ";\"");
dados[0] = st.nextToken();
dados[1] = st.nextToken();
dados[2] = st.nextToken();
dados[3] = st.nextToken();
dados[4] = st.nextToken();
dados[5] = st.nextToken();
DateFormat dateFormat = new SimpleDateFormat("d-M-yy");
PreparedStatement stmt = (PreparedStatement) conexao.prepareStatement("replace into registos"
+ " (data_registo, hora_registo, IdSensor, Temperatura, Humidade, pt_orvalho) values (?,?,?,?,?,?)");
try {
stmt.setDate(1, new java.sql.Date(dateFormat.parse(dados[0]).getTime()));
stmt.setString(2, dados[1]);
stmt.setString(3, dados[2]);
stmt.setString(4, dados[3]);
stmt.setString(5, dados[4]);
stmt.setString(6, dados[5]);
} catch (java.text.ParseException ex) {
Exceptions.printStackTrace(ex);
}
stmt.executeUpdate();
linha = reader.readLine();
PrintWriter writer = new PrintWriter("C:/Users/RPR1BRG/Desktop/test.txt");
writer.print("");
writer.close();
Verifica();
}
} catch (ClassNotFoundException | SQLException | IOException e) {
System.err.println("Erro: " + e.getMessage());
}finally{
if(conexao!=null)
conexao.close();
}
This kind of problem arises when you are NOT properly closing the connection after usage.
Please use finally block after catch to close the connections appropriately. This is because to ensure that the connection gets closed properly even when there is an unexpected exception or error. Please note that statements inside finally block gets executed always. it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break
Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
As you have asked in comment, I have added the code sample to demonstrate practically!
Connection con = null
try{
//Establishing connection to datasource
con = DBConnection.getConnection();
//perform DB operations
...
...
...
}catch(SQLException sqlEx){
/*To catch any SQLException thrown during DB
*Operations and continue processing like sending alert to admin
*that exception occurred.
*/
}finally{
/*This block should be added to your code
* You need to release the resources like connections
*/
if(con!=null)
con.close();
}
Please note that the declaration of Connection variable should be in proper scope to close it in finally block.
Hope this helps!
This may be because of the configured max_connections is not suitable with the Connection Pool size set in JDBC or number of connections you open against DB.
to check number of max_connections in mysql:
show variables like 'max_connections';
make sure you have proper value of opened connections with the DB Max connections.
As from Java 7, java.sql.Connection is AutoCloseable. From now on, you can write your code like this:
try(Connection con = (Connection) DriverManager.getConnection(url, username, pazzword)) {
//your statements
}catch(RuntimeException e) {
}
Restart apache tomcat server will work. This worked for me.
Welcome