I have a one to many relationship between User and GameMap. One user can have many maps.
User class:
// LAZY LOADED
@OneToMany(cascade = CascadeType.ALL, mappedBy = "creater")
private final List<GameMap> maps = new ArrayList<>();
However, sometimes I need to eager load the maps. To avoid the LazyInitializationException after closing Session, I have two variants of retrieving Users.
User Repository:
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findById( Long id );
@Query("SELECT u FROM User u JOIN FETCH u.maps WHERE u.id = (:id)")
public User findByIdEagerFetch( @Param("id") Long id );
}
Problem:
However, the JPQL JOIN FETCH variant to eager load in one go the user and his maps returns a NULL user if there are no maps for this user in the table.
Question:
How can I rewrite the JPQL statement in order to retrieve the user and optionally(!) all his maps but if there are no maps, than thats okay, but dont return a NULL user.
left-join-fetch to create join fetches with native queries. Note: This uses an OUTER join to allow null or empty values.
Coalesce is supported by JPA 2.0 API. The new construct is proprietary to Hibernate, not necessarily supported in all JPA implementations. First try the query without also trying to construct an object: select COALESCE(k.projectId,'N') as projectId, k.projectName from Emp o inner join o.projects k.
JPQL supports the five aggregate functions of SQL: COUNT - returns a long value representing the number of elements. SUM - returns the sum of numeric values. AVG - returns the average of numeric values as a double value.
The IS EMPTY operator is the logical equivalent of IS NULL, but for collections. Queries can use IS EMPTY operator or IS NOT EMPTY to check whether a collection association path resolves to an empty collection or has at least one value. We can use the EMPTY to check if a property is empty.
A FETCH JOIN
actually will resolve to an inner join in SQL. This means that any records/entities in the User
table which have no maps will be removed from the result set. You need the LEFT
keyword on your FETCH JOIN
to get all the results, even those without a map.
@Query("SELECT u FROM User u LEFT JOIN FETCH u.maps WHERE u.id = (:id)")
public User findByIdEagerFetch( @Param("id") Long id );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With