Enable Javascript

Please enable Javascript to view website properly

Toll Free 1800 889 7020

Looking for an Expert Development Team? Take 2 weeks Free Trial! Try Now

Overview of FetchMode in Spring Data JPA

Overview

In the current tutorial, we will get to know what is fetchMode, how it is used to fetch the entity and an introduction to @org.hibernate.annotations.Fetch annotation.

FetchMode in Spring Data JPA

Setting up the Example

As an example, we will use a Customer entity with two properties, an id and a set of orders.

Customer.java @Entity @Table(name = "CUSTOMER") public class Customer { @Id @GeneratedValue private Long id; @OneToMany @Fetch(FetchMode.SELECT) private Set < Orders> orders = new HashSet < Orders> (); //setters and getters }

Next, we will create the Orders entity, consisting of the Customer entity as a reference.

Orders.java @Entity @Table(name = "ORDERS") public class Orders { @Id @GeneratedValue private Long id; private String name; @ManyToOne @JoinColumn(name = "customer_id") private Customer customer; //setters and getters }

Next using the test class, we will understand the usage of @Fetch annotation.

From fetching the customer details from the database, we are using Hibernate session.

Below is the code to get customer details along with orders from the database.

Customer customter = session.get(Customer.class, id); Set<Order> orders = customer.getOrders();

But there can be different ways to fetch the orders from the database, either we can join with the Customer entity to get the details or generate a single query for we can use another query to get all the order details.

1) FetchMode.SELECT

it is the default strategy, it will use for fetching dependent lazily.

@OneToMany @Fetch(FetchMode.SELECT) private Set<Orders> orders = new HashSet<Orders>();

Fetch is used to describe how to hibernate should retrieve the dependent property when we lookup for a parent entity.

Using SELECT Hibernate will fetch orders entity lazily.

For suppose we want to fetch all the customers and their orders the code will look like the below:

Session session = sessionFactory.openSession(); List < Customer> cusomter1 = session.createCriteria(Customer.class).list(); for (Customer cus: cusomter1) { assertTrue(cus.getOrders().stream().allMatch(order - > order.getCustomer().getId() > 0)); }

This will result in the below-generated SQL statements.

Hibernate: select this_.id as id1_0_0_ from CUSTOMER this_ Hibernate: select orders0_.Customer_id as Customer1_1_0_, orders0_.orders_id as orders_i2_1_0_, orders1_.id as id1_2_1_, orders1_.customer_id as customer3_2_1_, orders1_.name as name2_2_1_, customer2_.id as id1_0_2_ from CUSTOMER_ORDERS orders0_ inner join ORDERS orders1_ on orders0_.orders_id=orders1_.id left outer join CUSTOMER customer2_ on orders1_.customer_id=customer2_.id where orders0_.Customer_id=? (Repeated for each customer)

For each customer it will fetch the orders using an individual query, this will result in a very well-known n+1 select problem. The first query is used to fetch the customers, and n queries are used for fetching each customer.

2) @BatchSize

Fetch mode is an optional configuration to specify the batch size, instead of retrieving each customer order separately, Hibernate will fetch orders using batches. Using @BatchSize we can configure the batch size. This way we can decrease the number of queries required to fetch the orders.

@OneToMany @Fetch(FetchMode.SELECT) @BatchSize(size = 2) private Set<Orders> orders = new HashSet<Orders>(); And generated Hibernate SQL statements look like below: Hibernate: select orders0_.Customer_id as Customer1_1_2_, orders0_.orders_id as orders_i2_1_2_, orders1_.id as id1_2_0_, orders1_.customer_id as customer3_2_0_, orders1_.name as name2_2_0_, customer2_.id as id1_0_1_ from CUSTOMER_ORDERS orders0_ inner join ORDERS orders1_ on orders0_.orders_id=orders1_.id left outer join CUSTOMER customer2_ on orders1_.customer_id=customer2_.id where orders0_.Customer_id in (?, ?)

3) FetchMode.JOIN

It is almost the same eager loading, the orders and customer entities are queries using the same query.

@OneToMany @Fetch(FetchMode.JOIN) private Set<Orders> orders = new HashSet<Orders>();

In this case, only a single query does execute for all required entities.

Hibernate generated SQL statement will look like this:

Hibernate: select this_.id as id1_0_2_, orders2_.Customer_id as Customer1_1_4_, orders3_.id as orders_i2_1_4_, orders3_.id as id1_2_0_, orders3_.customer_id as customer3_2_0_, orders3_.name as name2_2_0_, customer4_.id as id1_0_1_ from CUSTOMER this_ left outer join CUSTOMER_ORDERS orders2_ on this_.id=orders2_.Customer_id left outer join ORDERS orders3_ on orders2_.orders_id=orders3_.id left outer join CUSTOMER customer4_ on orders3_.customer_id=customer4_.id

4) FetchMode.SUBSELECT

it is used only if the nested property is a type of collection.

@OneToMany @Fetch(FetchMode.SUBSELECT) private Set<Orders> orders = new HashSet<Orders>();

Using this fetchmode, only 2 queries will execute, one for fetching the customers, and one more query for fetching all customer orders.

And the Hibernate Generated queries look like below:

Hibernate: select this_.id as id1_0_0_ from CUSTOMER this_ Hibernate: select orders0_.Customer_id as Customer1_1_2_, orders0_.orders_id as orders_i2_1_2_, orders1_.id as id1_2_0_, orders1_.customer_id as customer3_2_0_, orders1_.name as name2_2_0_, customer2_.id as id1_0_1_ from CUSTOMER_ORDERS orders0_ inner join ORDERS orders1_ on orders0_.orders_id=orders1_.id left outer join CUSTOMER customer2_ on orders1_.customer_id=customer2_.id where orders0_.Customer_id in (select this_.id from CUSTOMER this_)

FetchMode vs. FetchType

In general, FetchMode defines how Hibernate will fetch the data (by select, join or subselect). FetchType, on the other hand, defines whether Hibernate will load data eagerly or lazily.

The exact rules between these two are as follows:

  • 1) if the code doesn’t set FetchMode, the default one is JOIN, and FetchType works as defined
  • 2) with FetchMode.SELECT or FetchMode.SUBSELECT set, FetchType also works as defined
  • 3) With FetchMode.JOIN set, FetchType is ignored and a query is always eager

You should keep some points in mind when you hire Java developers such as they should be able to solve problems.

Conclusion

In this tutorial, we learned about what FetchMode is, how to use Hibernate internally to fetch entity mappings, and different types of FetchModes and their usage. Finally, we understood the differences between Fetch Mode and FetchType.

Source code: Hibenet Example Code

Software Development Team
Need Software Development Team?
captcha
🙌

Thank you!
We will contact soon.

Oops! Something went wrong.

Recent Blogs

Categories

NSS Note
Trusted by Global Clients