Hibernate - Batch Processing

Last Updated : 25 Mar, 2026

Hibernate stores newly inserted objects in the second-level cache, which can lead to OutOfMemoryException when inserting very large datasets (e.g., millions of records). Batch processing helps efficiently handle such large data operations.

  • Reduces memory usage by processing records in chunks instead of all at once.
  • Improves performance by minimizing database round trips through batching.

Note: Set hibernate.jdbc.batch_size (typically 10–50) to enable batching; a zero or negative value disables it.

Let us use the JPA @TableGenerator annotation to generate the unique key for the entity. As we are not sure of how many records were inserted because of the batch, the IDENTITY generator is disabled by Hibernate.

Step-by-Step Implementation of Hibernate - Batch Processing

Follow the below steps to efficiently implement batch processing in Hibernate for handling large volumes of data.

Step 1: Create Maven Project

  • Create a Maven project (e.g., hibernate-batching-example)
  • Set Java version (1.8 or above)
  • This is a maven-driven project

Project Structure:

 

Step 2: Add Dependencies (pom.xml)

Add required libraries:

  • hibernate-core
  • mysql-connector-java
  • jaxb-api
  • log4j (for logging)

pom.xml

XML
<project xmlns="https://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 
                       https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.gfg.hibernate.batch</groupId>
   <artifactId>hibernate-batching-example</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <properties>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
   </properties>
<dependencies>
   <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.4.15.Final</version>
   </dependency>
   <!-- mysql connector dependency -->
   <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.34</version>
   </dependency>
   <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.3.0</version>
   </dependency>

   <!--Log4j2 API -->
   <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.11.0</version>
   </dependency>
   <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>2.11.0</version>
   </dependency>
</dependencies>
</project>

Step 3: Configure Logging

  • Create log4j2.xml
  • Enable Hibernate batch logging for debugging
XML
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
   <Appenders>
      <!-- Console Appender -->
      <Console name="Console" target="SYSTEM_OUT">
         <PatternLayout pattern="%d{yyyy-MMM-dd HH:mm:ss a} [%t] %-5level %logger{36} - %msg%n" />
      </Console>
   </Appenders>
   <Loggers>
      <!-- Log everything in hibernate -->
      <Logger name="org.hibernate.engine.jdbc.batch.internal.BatchingBatch" level="debug" additivity="false">
         <AppenderRef ref="Console" />
      </Logger>
      <Root level="error">
         <AppenderRef ref="Console" />
      </Root>
   </Loggers>
</Configuration>

Step 4: Create Entity Class (Product)

  • Annotate class with @Entity
  • Add fields: id, productName, productBrand, price
  • Use: @Id , @GeneratedValue , @TableGenerator (for batch insert IDs)
  • Add getters, setters, and default constructor

Product.java

Java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.TableGenerator;

@Entity
public class Product {

    @Id
    @TableGenerator(name = "PRODUCT_SEQ")
    // As we are doing batch insert, using TableGenerator,
    // unique key is determined
    @GeneratedValue(strategy = GenerationType.TABLE,
                    generator = "PRODUCT_SEQ")
    // data members of product
    private Long id;

    private String productName;
    private String productBrand;
    private int price;
    // Getter and setters

    public Long getId() { return id; }

    public void setId(Long id) { this.id = id; }

    public String getProductName() { return productName; }

    public void setProductName(String productName)
    {
        this.productName = productName;
    }

    public String getProductBrand() { return productBrand; }

    public void setProductBrand(String productBrand)
    {
        this.productBrand = productBrand;
    }

    public int getPrice() { return price; }

    public void setPrice(int price) { this.price = price; }
    // This is essentially required to avoid exceptions
    public Product() {}
}

Step 5: Create Hibernate Utility Class

  • Create HibernateUtil.java
  • Configure: Database connection (URL, username, password) , Dialect & driver , HBM2DDL_AUTO = update
  • Batch size using:

Environment.STATEMENT_BATCH_SIZE = 50;

  • Build SessionFactory

HibernateUtil.java

Java
import com.gfg.hibernate.batch.entity.Product;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment;

public class HibernateUtil {
    private static StandardServiceRegistry registry;
    private static SessionFactory sessionFactory;

    public static SessionFactory getSessionFactory()
    {
        if (sessionFactory == null) {
            try {
                StandardServiceRegistryBuilder
                    registryBuilder
                    = new StandardServiceRegistryBuilder();

                // Configuration properties
                Map<String, Object> settings
                    = new HashMap<>();

                settings.put(Environment.DRIVER,
                             "com.mysql.jdbc.Driver");

                settings.put(
                    Environment.URL,
                    "jdbc:mysql://localhost:3306/geeksforgeeks?serverTimezone=UTC");
                // Specify mySQL credentials here
                settings.put(Environment.USER, "root");
                settings.put(Environment.PASS, "admin");

                settings.put(Environment.HBM2DDL_AUTO,
                             "update");
                // Set JDBC batch size. It can be set
                // between 10 and 50
                settings.put(
                    Environment.STATEMENT_BATCH_SIZE, 50);

                registryBuilder.applySettings(settings);
                registry = registryBuilder.build();

                MetadataSources sources
                    = new MetadataSources(registry);
              
                // This entity class Product is going to be
                // used for batch insert or update
                sources.addAnnotatedClass(Product.class);
                Metadata metadata
                    = sources.getMetadataBuilder().build();

                sessionFactory
                    = metadata.getSessionFactoryBuilder()
                          .build();
            }
            catch (Exception e) {
                if (registry != null) {
                    StandardServiceRegistryBuilder.destroy(
                        registry);
                }
                e.printStackTrace();
            }
        }
        return sessionFactory;
    }

    public static void shutdown()
    {
        if (registry != null) {
            StandardServiceRegistryBuilder.destroy(
                registry);
        }
    }
}

Step 6: Implement Batch Insert

Create InsertProductBatchExample.java . Steps are following :

  1. Open session
  2. Begin transaction
  3. Loop (e.g., 100 records)
  4. Save objects using session.save()
  5. After batch size (e.g., 10): Call session.flush() and Call session.clear()
  6. Commit transaction
  7. Close session

InsertProductBatchExample.java

Java
import com.gfg.hibernate.batch.entity.Product;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class InsertProductBatchExample {
    public static void main(String[] args)
    {
        Session session = null;
        Transaction transaction = null;
        // Setting zero or negative number will disable the
        // batching.
        int batchSize
            = 10; // As of now, it is hardcoded to 10
        try {
            session = HibernateUtil.getSessionFactory()
                          .openSession();
            transaction = session.beginTransaction();
            // Here as a sample 100 items are inserted, but
            // it can be changed as per user choice
            for (long idx = 1; idx <= 100; idx++) {
                Product product = new Product();
                // We can use this as sample. Please change
                // according to the requirement
                product.setProductName("Product" + idx);
                product.setProductBrand("A");
                product.setPrice((int)idx * 10);
                session.save(product);
                if (idx > 0
                    && idx % batchSize
                           == 0) { // Keep on doing this
                                   // step in order to
                                   // continue and avoid
                                   // exceptions
                    session.flush();
                    session.clear();
                }
            }
            transaction.commit();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (session != null) {
                session.close();
            }
        }

        HibernateUtil.shutdown();
    }
}

Step 7: Run Insert Program

  • Executes batch insert
  • Data inserted in groups (improves performance)
 

Step 8: Verify Database

  • Check MySQL table
  • Confirm records are inserted in bulk
 

Step 9: Implement Batch Update

Create UpdateProductBatchExample.java Steps:

  1. Open session & transaction
  2. Fetch records using ScrollableResults
  3. Loop through records
  4. Update values (e.g., price)
  5. After batch size: session.flush() and session.clear()
  6. Commit transaction

UpdateProductBatchExample.java

Java
import com.gfg.hibernate.batch.entity.Product;
import org.hibernate.CacheMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class UpdateProductBatchExample {
    public static void main(String[] args)
    {
        Session session = null;
        Transaction transaction = null;
        // As we are going to do bulk operations, we need
        // ScrollableResults
        ScrollableResults scrollableResults = null;
        // Setting zero or negative number will disable the
        // batching.
        int batchSize = 10; // It can be between 10 and 50.
        try {
            session = HibernateUtil.getSessionFactory()
                          .openSession();
            transaction = session.beginTransaction();
            scrollableResults
                = session
                      .createQuery(
                          "from Product") // Query the table
                      .setCacheMode(CacheMode.IGNORE)
                      .scroll(
                          ScrollMode
                              .FORWARD_ONLY); // We have to
                                              // get all
                                              // records
            int count = 0;
            int price = 1;
            while (scrollableResults.next()) {
                Product product
                    = (Product)scrollableResults.get(0);
                product.setPrice(
                    price
                    + (price
                       * 10)); // update the price, this is
                               // just a sample
                price += 1;
                if (++count % batchSize
                    == 0) { // This is much required
                    session.flush();
                    session.clear();
                }
            }
            transaction.commit();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (scrollableResults != null) {
                scrollableResults.close();
            }
            if (session != null) {
                session.close();
            }
        }
        HibernateUtil.shutdown();
    }
}

Step 10: Run Update Program

  • Updates records in batches
  • Efficient for large data
 

Step 11: Verify Updated Data

Check updated values in database

MySQL output is as follows:

Comment