I am inserting data from java in to postgresql database. I am using jdbc postgresql driver to make connection. I am creating a batch of statements and sending to insert in one go. But if connection is lost then java tries to connect with database again using connection pooling. I tried to execute the batch again but no record is inserted.
PreparedStatement pstmt = connection.prepareStatement(INSERT_RECORD_TABLE_SQL);
while (iterator.hasNext()) {
pstmt.setLong(1, toLong(fields[0]));
pstmt.setLong(2, toLong(fields[1]));
....
pstmt.addBatch();
}
try{
pstmt.executeBatch();
} catch (Exception e) {
Thread.sleep(60000);
pstmt.executeBatch();
}
My question is that Can I retain the batch of statements that can be executed if exception occurs?
Thanks,
Saurabh Gupta
It is a bad thing to catch the general Exception.
It is a bad thing to sleep for a minute, or any other "human" time value.
It is a bad thing to re-execute the same code in the catch block just like if nothing had occurred, but you're handling an exception there! And you should catch the new possible exception in the catch block.
Better to:
try
{
int[] updateCounts = pstmt.executeBatch();
}
catch (BatchUpdateException be)
{
// if one of the commands sent to the database fails to execute properly
// or attempts to return a result set
handleException(be);
return;
}
catch (SQLException se)
{
//if a database access error occurs, this method is called on a closed Statement
//or the driver does not support batch statements
handleException(se);
return;
}
Do you need a transaction? That is, if an error occurs should you rollback to the state the db was before you started, or is it ok to retry?
Related
sorry my english.
I have a problem for some time and I have no idea what to do to solve it, I have a legacy application in Java 5 that uses JDBC to execute a procedure in the SQL Server database that processes a lot of information, this process occurs perfectly and takes a 30 minutes to complete, now I am migrating this application to Java EE with eclipse link, when calling the same procedure in this new system it takes much longer to complete, it has already run for more than 15 hours, unfortunately I do not have access from DBA to the bank to analyze the processes in more depth.
Apparently the problem occurs when there is a lot of data, because in the test bank the execution time in both systems are similar, now when I run with a bank with more data this anomaly occurs.
I changed the code to get the EntityManager connection and run it with JDBC, but without success.
Currently my code is like this:
public void calcula(Integer idProc) {
pegaConexaoJDBC();
String sql = "{call PRO_EQU_CALCULA(?)}";
CallableStatement st = null;
try {
st = connection.prepareCall(sql);
st.setInt(1, idProc);
st.execute();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
st = null;
}
}
}
I performed several tests for days and did not get a solution, can anyone help me?
In our web application we are running into this issue very often
ORA-01000 maximum open cursors exceeded
I understand this has to do with the code not closing the cursors (ResultSet, PreparedStatement, etc.) properly.
Sample:
public List<Employee> getAllEmployees() throws DatabaseException{
Connection conn = DatabaseHelper.getConnection(); //Get a connection from the connection pool
PreparedStatement pst = null;
ResultSet rs = null;
List<Employee> emps = new ArrayList<Employee>();
try {
pst = conn.prepareStatement("SELECT * FROM EMPLOYEE ORDER BY EMP_ID");
rs = pst.executeQuery();
while(rs.next()) {
//Do something
}
} catch (SQLException e) {
logger.error("ERROR getting all employees", e);
throw new DatabaseException("Could not get all employees due to an internal error", e);
} finally {
try { pst.close(); } catch(Exception ignore) {} //Close the prepared statement
try { rs.close(); } catch(Exception ignore) {} //Close the Resultset
try { conn.close(); } catch(Exception ignore) {} ////Close the connection, thus returning it to the pool
}
return emps;
}
Though I understand that I'm closing the cursors and the connection in the finally block, what I don't understand is how can I actually verify that the cursors are closed in the Oracle database?
I am currently running the following query (assuming my DB username is EMP)
select * from v$open_cursor where sid in (select sid from v$session where username='EMP' and program ='JDBC Thin Client');
This gives me a list of rows for open cursors for sessions connected through the JDBC thin client. But even after the pst.close(), rs.close() and the conn.close() are called, the query keeps returning the same rows, which seems to indicate that the cursors are still open.
I used JProfiler to check for leaks. However, it tells me if I'm closing the Connection objects or not, but does not tell me about PreparedStatement, Statement and ResultSet
I have already referred to the following post, and have followed the instructions, but none of them seem to answer my question, which is, how can I verify if a cursor is being closed in Oracle (using SQL Developer or some other tool)?
Link to a very exhaustive explanation on this topic
First, and most important, v$open_cursor is not a list of cursors currently open. For that, I think you need some combination of v$sesstat and v$statname, but I'm not really sure.
What is your open_cursors parameter set to? I think the default is 50, but Oracle recommends setting that to at least 500.
I'm a student and one of our assignments is creating a Java web project on a local GlassFish 5 webserver. The database used for this project is an OracleDB running locally in a Docker container.
I almost finished my project but some pages keep crashing (NullPointerException). I have to retrieve database records and save them in an ArrayList. But sometimes the SQLConnection doesn't return anything (but the records DO exist) and my code tries to preform actions on that empty ArrayList.
Now, as I said, the connection appears to be unstable, because at some seemingly random moments the database does respond with the appropriate records.
It's really frustrating and I cannot continue working on this project without a stable database connection. So I'd appreciate hearing from people with some more experience :-)
Thank you for your time.
Code for running a query:
protected ResultSet getRecords(String query) {
try {
Connection connection = DriverManager.getConnection(url, login, password);
Statement statement = connection.createStatement();
return (ResultSet) statement.executeQuery(query);
} catch (SQLException e) {
e.getStackTrace();
}
return null;
}
Code with the query:
List<Uitlening> uitleningen = new ArrayList<Uitlening>();
try {
ResultSet resultSet = getRecords("SELECT * FROM uitlening");
while(resultSet.next()) { //Here the code crashes because the ResultSet can sometimes be empty.
I think this is the actual error message: Listener refused the connection with the following error: ORA-12519, TNS:no appropriate service handler found
But I don't really understand what I should do now..
try {
ResultSet resultSet = getRecords("SELECT * FROM uitlening");
while(resultSet.next()) {
Uitlening uitlening = new Uitlening();
uitlening.setNr(resultSet.getInt("nr"));
uitleningen.add(uitlening);
}
} catch (SQLException e) {
e.addSuppressed(e);
}
return uitleningen;
It might be nothing, but it almost looks like the error only occurs when I run 2 queries almost immediately after each other. Is it possible that closing the connection takes a while?
Chances are that you run into the database connection problem because your code does not properly close the database connections as well as the statements and result sets.
A statement will also close its active result set. Most JDBC will also close the statement if the connection is closed.
So closing the connection is the most important part. It cannot be achieved with your current code structure because you create it in an inner method and do not return it.
It has also been mentioned that the exception handling is poor because you ignore exceptions and return null instead causing seemingly unrelated crashes later. In many cases it might be easier to declare that the method throws SQLException.
You might want to change your code like so:
List<Uitlening> retrieveData() {
final String query = "SELECT * FROM uitlening";
try (Connection connection = DriverManager.getConnection(url, login, password);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query)) {
return processResultSet(resultSet);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
List<Uitlening> processResultSet(ResultSet resultSet) throws SQLException {
List<Uitlening> uitleningen = new ArrayList<>();
while (resultSet.next()) {
Uitlening uitlening = new Uitlening();
uitlening.setNr(resultSet.getInt("nr"));
uitleningen.add(uitlening);
}
return uitleningen;
}
It closes the connection, the statement and the result set by using try/catch blocks that take advantage of AutoClosables (in this case: Connection, Statement, ResultSet).
The method processResultSet declares the SQLException so it doesn't need to handle it.
The code is rearrange so the data is fully processed before the code leaves the try/catch block that closes the connection.
I have a function to insert data using JDBC but it works just for one record how can insert multiple records dynamicaly
public void insertInfo() throws Exception{
try{
int codeNat = getNat();
String query = "INSERT INTO info (id,name,code_nat) VALUES (?,?,?)";
stat = cnx.prepareStatement(query);
stat.setString(1, txtId.getText());
stat.setString(2, txtName.getText());
stat.setInt(3, codeNat);
stat.execute();
Update_table();
}catch(SQLException ex){
JOptionPane.showMessageDialog(null,ex);
}
finally{
try{
stat.close();
cnx.close();
}catch(Exception e){
}
}
}
the exception i had "No operations allowed after connection closed."
You are closing your connection (cnx) in the finally of your method. This will close the connection the first time you insert (whether it fails or passes) and then the connection will still be closed the next time you come along to insert. You can try moving the connection opening into this method if you like, but connection can be expensive to open/close, perhaps move the closing/opening outside this method. It's really hard to say until we see more of the code you're working on.
I was working on a servlet that will generate a unique code and update that in a mySQL database.
Now, in that, I want to catch any exception thrown in case that unique code already exists in the mySQL table and generate a new code and try updating the database. The problem is I want to do this WITHIN the for loop itself. The code is as follows:
try
{
connection = datasource.getConnection();
SQLUpdate = "INSERT INTO Voucher_dump VALUES( '"+unique_code+"','08-10-2011 04:48:48','0')";
PreparedStatement ps1 = connection.prepareStatement(SQLUpdate);
ps1.executeUpdate();
ResultSet r = ps1.getResultSet(); // this is where I'm checking if it's a duplicate
if(r==null)
out.println("This is a duplicate");
else out.println("Updated");
trial12= "08-10-2011 04:48:480.03999855056924717a";
SQLUpdate = "INSERT INTO Voucher_dump VALUES( '"+trial12+"','08-10-2011 04:48:48','0')";
ps1 = connection.prepareStatement(SQLUpdate);
ps1.executeUpdate();
r = ps1.getResultSet();
if(r==null)
out.println("This is a duplicate");
else out.println("Updated");
}
catch (SQLException sqle)
{
sqle.printStackTrace();
}
I don't want to wait till the end of the entire loop to catch the SQLException (I have already defined this key in mySQL as primary). The moment, the result comes back as a duplicate entry, I want to re-generate this key and attempt the update again.My output for this particular code is coming blank on my output page (all other parameters are showing correctly). Neither is "This is a duplicate" displayed nor is "Updated". Maybe, ResultSet is not the best way to do it. Could you guys give me some advice on what would be the best way forward ?
Some advice in no particular order:
Close the connection in a finally block.
Close statements individually if you'll be creating many of them before closing the connection. ("Many" is defined by your DBAs.)
Format your code.
Don't use stdout and/or stderr from real code. Pick a logging framework.
Consider using some helper classes to simplify (and correct) your database access, like Spring's JdbcTemplate.
Make sure to include relevant context when you post example code.
Due to #6, I don't know what out is, but I suspect the reason you're not seeing anything is that you're inserting a duplicate value with the first statement, which will cause a SQLException from that line, not at getResultSet(), where you seem to expect it. Since the error is written to stdout, it'll show up in your server logs somewhere, but nothing will be written to out. I'm not sure why you think getResultSet() will return null or not null depending on whether there was a constraint violation. Take a look at the javadoc for that method.
Update: 7. As BalusC points out, never, ever concatenate a string directly into a JDBC Statment. Use PreparedStatment's placeholders and set* methods. For info on SQL injection, see Wikipedia and XKCD.
How about this code?
try {
Class.forName(driver).newInstance();
conn = DriverManager.getConnection(url + dbName);
System.out.println("Connected to the database");
int i = 1; //get the unique code
boolean isInserted = false;
while (!isInserted) {
try {
PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO test values (?)");
preparedStatement.setInt(1, i);
preparedStatement.executeUpdate();
isInserted = true;
} catch (com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException e) { //Catch the particular exception which throws error on unique constraint. This may depend on Java/MySQL your version
i++; //get the next unique code
}
}
System.out.println("Disconnected from database");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (Exception e) {
}
}