2020-04-24

Hibernate JPA @BatchSize annotation Example

@BatchSize

The @BatchSize annotation is used to specify the size for batch loading the entries of a lazy collection.

BatchSize Defines size for batch loading of collections or lazy entities. For example...
     @Entity
     @BatchSize(size=100)
     class Product {
         ...
     }

will initialize up to 100 lazy Product entity proxies at a time.
        @OneToMany
        @BatchSize(size = 5) /
        Set getProducts() { ... };

will initialize up to 5 lazy collections of products at a time.

Hibernate offers the @BatchSize annotation, which can be used when fetching uninitialized entity proxies.

Considering the following entity mapping:

@BatchSize mapping example
@Entity(name = "Department")
public static class Department {

@Id
private Long id;

@OneToMany(mappedBy = "department")
//@BatchSize(size = 5)
private List<Employee> employees = new ArrayList<>();

//Getters and setters omitted for brevity

}

@Entity(name = "Employee")
public static class Employee {

@Id
private Long id;

@NaturalId
private String name;

@ManyToOne(fetch = FetchType.LAZY)
private Department department;

//Getters and setters omitted for brevity
}

Considering that we have previously fetched several Department entities, and now we need to initialize the employees entity collection for each particular Department, the @BatchSize annotations allows us to load multiple Employee entities in a single database roundtrip.

@BatchSize fetching example

List<Department> departments = entityManager.createQuery(
"select d " +
"from Department d " +
"inner join d.employees e " +
"where e.name like 'John%'", Department.class)
.getResultList();

for ( Department department : departments ) {
log.infof(
"Department %d has {} employees",
department.getId(),
department.getEmployees().size()
);
}

Without @BatchSize, you’d run into a N+1 query issue, so, instead of 2 SQL statements, there would be 10 queries needed for fetching the Employee child entities.

However, although @BatchSize is better than running into an N+1 query issue, most of the time, a DTO projection or a JOIN FETCH is a much better alternative since it allows you to fetch all the required data with a single query.

No comments:

Post a Comment