Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing a PreparedStatement multiple times

in the case of using PreparedStatement with a single common connection without any pool, can I recreate an instance for every dml/sql operation mantaining the power of prepared statements?

I mean:

for (int i=0; i<1000; i++) {     PreparedStatement preparedStatement = connection.prepareStatement(sql);     preparedStatement.setObject(1, someValue);     preparedStatement.executeQuery();     preparedStatement.close(); } 

instead of:

PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i=0; i<1000; i++) {     preparedStatement.clearParameters();     preparedStatement.setObject(1, someValue);     preparedStatement.executeQuery(); } preparedStatement.close(); 

my question arises by the fact that I want to put this code into a multithreaded environment, can you give me some advice? thanks

like image 873
Steel Plume Avatar asked Mar 18 '10 01:03

Steel Plume


People also ask

Can I use same PreparedStatement multiple times?

Once a PreparedStatement is prepared, it can be reused after execution. You reuse a PreparedStatement by setting new values for the parameters and then execute it again.

Which is faster Statement or PreparedStatement?

Prepared statements are much faster when you have to run the same statement multiple times, with different data. Thats because SQL will validate the query only once, whereas if you just use a statement it will validate the query each time.

When should I close PreparedStatement?

Closing PreparedStatement ObjectIf you close the Connection object first, it will close the PreparedStatement object as well. However, you should always explicitly close the PreparedStatement object to ensure proper cleanup.


1 Answers

The second way is a tad more efficient, but a much better way is to execute them in batches:

public void executeBatch(List<Entity> entities) throws SQLException {      try (         Connection connection = dataSource.getConnection();         PreparedStatement statement = connection.prepareStatement(SQL);     ) {         for (Entity entity : entities) {             statement.setObject(1, entity.getSomeProperty());             // ...              statement.addBatch();         }          statement.executeBatch();     } } 

You're however dependent on the JDBC driver implementation how many batches you could execute at once. You may for example want to execute them every 1000 batches:

public void executeBatch(List<Entity> entities) throws SQLException {      try (         Connection connection = dataSource.getConnection();         PreparedStatement statement = connection.prepareStatement(SQL);     ) {         int i = 0;          for (Entity entity : entities) {             statement.setObject(1, entity.getSomeProperty());             // ...              statement.addBatch();             i++;              if (i % 1000 == 0 || i == entities.size()) {                 statement.executeBatch(); // Execute every 1000 items.             }         }     } } 

As to the multithreaded environments, you don't need to worry about this if you acquire and close the connection and the statement in the shortest possible scope inside the same method block according the normal JDBC idiom using try-with-resources statement as shown in above snippets.

If those batches are transactional, then you'd like to turn off autocommit of the connection and only commit the transaction when all batches are finished. Otherwise it may result in a dirty database when the first bunch of batches succeeded and the later not.

public void executeBatch(List<Entity> entities) throws SQLException {      try (Connection connection = dataSource.getConnection()) {         connection.setAutoCommit(false);          try (PreparedStatement statement = connection.prepareStatement(SQL)) {             // ...              try {                 connection.commit();             } catch (SQLException e) {                 connection.rollback();                 throw e;             }         }     } } 
like image 192
BalusC Avatar answered Oct 17 '22 20:10

BalusC