[java] What is the difference between JOIN and JOIN FETCH when using JPA and Hibernate

Please help me understand where to use a regular JOIN and where a JOIN FETCH.

For example, if we have these two queries

FROM Employee emp
JOIN emp.department dep

and

FROM Employee emp
JOIN FETCH emp.department dep

Is there any difference between them? If yes, which one to use when?

This question is related to java hibernate join hql fetch

The answer is


Dherik : I'm not sure about what you say, when you don't use fetch the result will be of type : List<Object[ ]> which means a list of Object tables and not a list of Employee.

Object[0] refers an Employee entity 
Object[1] refers a Departement entity 

When you use fetch, there is just one select and the result is the list of Employee List<Employee> containing the list of departements. It overrides the lazy declaration of the entity.


If you have @oneToOne mapping set to FetchType.LAZY and you use second query (because you need Department objects to be loaded as part of Employee objects) what Hibernate will do is, it will issue queries to fetch Department objects for every individual Employee object it fetches from DB.

Later, in the code you might access Department objects via Employee to Department single-valued association and Hibernate will not issue any query to fetch Department object for the given Employee.

Remember, Hibernate still issues queries equal to the number of Employees it has fetched. Hibernate will issue same number of queries in both above queries, if you wish to access Department objects of all Employee objects


JOIN

When using JOIN against an entity associations, JPA will generate a JOIN between the parent entity and the child entity tables in the generated SQL statement.

So, taking your example, when executing this JPQL query:

FROM Employee emp
JOIN emp.department dep

Hibernate is going to generate the following SQL statement:

SELECT emp.*
FROM employee emp
JOIN department dep ON emp.department_id = dep.id

Note that the SQL SELECT clause contains only the employee table columns, and not the department ones. To fetch the department table columns, we need to use JOIN FETCH instead of JOIN.

JOIN FETCH

So, compared to JOIN, the JOIN FETCH allows you to project the joining table columns in the SELECT clause of the generated SQL statement.

So, in your example, when executing this JPQL query:

FROM Employee emp
JOIN FETCH emp.department dep

Hibernate is going to generate the following SQL statement:

SELECT emp.*, dept.*
FROM employee emp
JOIN department dep ON emp.department_id = dep.id

Note that, this time, the department table columns are selected as well, not just the ones associated with the entity listed in the FROM JPQL clause.

Also, JOIN FETCH is a great way to address the LazyInitializationException when using Hibernate as you can initialize entity associations using the FetchType.LAZY fetching strategy along with the main entity you are fetching.


in this link i mentioned before on the comment, read this part :

A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections.

this "JOIN FETCH" will have it's effect if you have (fetch = FetchType.LAZY) property for a collection inside entity(example bellow).

And it is only effect the method of "when the query should happen". And you must also know this:

hibernate have two orthogonal notions : when is the association fetched and how is it fetched. It is important that you do not confuse them. We use fetch to tune performance. We can use lazy to define a contract for what data is always available in any detached instance of a particular class.

when is the association fetched --> your "FETCH" type

how is it fetched --> Join/select/Subselect/Batch

In your case, FETCH will only have it's effect if you have department as a set inside Employee, something like this in the entity:

@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;

when you use

FROM Employee emp
JOIN FETCH emp.department dep

you will get emp and emp.dep. when you didnt use fetch you can still get emp.dep but hibernate will processing another select to the database to get that set of department.

so its just a matter of performance tuning, about you want to get all result(you need it or not) in a single query(eager fetching), or you want to query it latter when you need it(lazy fetching).

Use eager fetching when you need to get small data with one select(one big query). Or use lazy fetching to query what you need latter(many smaller query).

use fetch when :

  • no large unneeded collection/set inside that entity you about to get

  • communication from application server to database server too far and need long time

  • you may need that collection latter when you don't have the access to it(outside of the transactional method/class)


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to hibernate

Hibernate Error executing DDL via JDBC Statement How does spring.jpa.hibernate.ddl-auto property exactly work in Spring? Error creating bean with name 'entityManagerFactory' defined in class path resource : Invocation of init method failed JPA Hibernate Persistence exception [PersistenceUnit: default] Unable to build Hibernate SessionFactory Disable all Database related auto configuration in Spring Boot Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] HikariCP - connection is not available Hibernate-sequence doesn't exist How to find distinct rows with field in list using JPA and Spring? Spring Data JPA and Exists query

Examples related to join

Pandas Merging 101 pandas: merge (join) two data frames on multiple columns How to use the COLLATE in a JOIN in SQL Server? How to join multiple collections with $lookup in mongodb How to join on multiple columns in Pyspark? Pandas join issue: columns overlap but no suffix specified MySQL select rows where left join is null How to return rows from left table not found in right table? Why do multiple-table joins produce duplicate rows? pandas three-way joining multiple dataframes on columns

Examples related to hql

Difference between INNER JOIN and LEFT SEMI JOIN [Ljava.lang.Object; cannot be cast to HQL Hibernate INNER JOIN What is the difference between JOIN and JOIN FETCH when using JPA and Hibernate IN-clause in HQL or Java Persistence Query Language ORDER BY using Criteria API How do you do a limit query in JPQL or HQL? Hibernate HQL Query : How to set a Collection as a named parameter of a Query? How do you create a Distinct query in HQL JPA and Hibernate - Criteria vs. JPQL or HQL

Examples related to fetch

Using Axios GET with Authorization Header in React-Native App Retrieve data from a ReadableStream object? Javascript: Fetch DELETE and PUT requests How do I POST with multipart form data using fetch? What is the difference between JOIN and JOIN FETCH when using JPA and Hibernate PHP PDO with foreach and fetch Failed to fetch URL https://dl-ssl.google.com/android/repository/addons_list-1.xml, reason: Connection to https://dl-ssl.google.com refused Trying to get property of non-object in php pdo: get the columns name of a table