7

Technology stack: Oracle database 11.2.0.2, Java 1.6, Hibernate 3.6.6.Final.

I am new to hibernate, apologize if this is trivial.

The following code was supposed to put some optimization:

Transaction tx = session.beginTransaction();
for (int i = 0; i < 10; i++) {
   POJO pojo = new POJO(i);
   session.save(pojo);
}
tx.commit();

hibernate.cfg.xml has the following entry

<property name="jdbc.batch_size">500</property>

How can I verify, if hibernate really batches all these inserts? If it performs 10 inserts than there is no gain. One idea is to put the jdbc plain query right after save() that checks if the record was added to db:

String query = "retrieve previously added element"
PreparedStatement stmt = session.connection().prepareStatement(query.toString());
Result rs = statement.executeQuery();
/** check contents of rs */

In my case it returns a non empty set with previously added element. Does it mean anything? How else can I check if batching works.

thanks in advance

Maciej Kowalski
  • 21,760
  • 10
  • 42
  • 54
Łukasz
  • 1,438
  • 3
  • 21
  • 40

2 Answers2

15

You need to add "BatchingBatch" logger to your logging provider.

org.hibernate.engine.jdbc.batch.internal.BatchingBatch

Than you will be able to see in the logs something like:

2018-02-20 17:33:41.279 DEBUG 6280 --- [           main] o.h.e.jdbc.batch.internal.BatchingBatch  : Executing batch size: 19

Unless you see this message,batching is not working.

Tested with Hibernate Version:5.2.12

selman
  • 975
  • 1
  • 12
  • 26
2

To check what is actually flushed to the database then configure your logging properties as follows:

log4j.rootLogger=info, stdout
# basic log level for all messages
log4j.logger.org.hibernate=debug

# SQL statements and parameters
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type.descriptor.sql=trace

and add this to your hibernate.cfg.xml

<property name="show_sql">true</property>

Then you can see what is actually sent to the db..

With batch you should have output like:

insert into Pojo (id , titel) values (1, 'val1') , (2, 'val2') ,(3, 'val3')

Additionally here is a good post that has some tips about how to most efficiently take advantage of the batch processing: article

For example you might consider flushing after every ${jdbc.batch_size} saves.

Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
    Customer customer = new Customer(.....);
    Cart cart = new Cart(...);
    customer.setCart(cart) // note we are adding the cart to the customer, so this object 
     // needs to be persisted as well
    session.save(customer);
    if ( i % 20 == 0 ) { //20, same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}
tx.commit();
Maciej Kowalski
  • 21,760
  • 10
  • 42
  • 54
  • Thanks. Unfortunately I am still seing single insert statements. – Łukasz Feb 03 '17 at 10:28
  • do you flush after ${jdbc.batch_size} saves? – Maciej Kowalski Feb 20 '17 at 21:56
  • 1
    The INSERT statement will only be rewritten into a big bulk INSERT if your JDBC driver supports that (I know MySQL can do this). That's a separate concern from batching inserts, however. You can see single inserts in the log but they can still be sent as a batch to the server. – Frans May 22 '18 at 12:11
  • For MYSQL also (Version 5.x), it shows single inserts in the log but in stats log, it displays the (n) batch statements executed – John Apr 23 '20 at 11:57