I have a development project using Spring Data JPA and MapStruct to map between Entities and DTOs. Last week I decided it was time to address the FetchType.EAGER
vs LAZY
issue I have postponed for some time. I choose to use @NamedEntityGraph
and @EntityGraph
to load properties when needed. However I am stuck with this LazyInitializationExeption
problem when doing the mapping from entity to dto. I think I know where this happens but I do not know how to get passed it.
The code
@NamedEntityGraph(name="Employee.full", ...)
@Entity
public class Employee {
private Set<Role> roles = new HashSet<>();
}
@Entity
public class Role {
private Set<Employee> employees = new HashSet<>();
}
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
@EntityGraph(value = "Employee.full")
@Override
Page<Employee> findAll(Pageable pageable);
}
@Service
public class EmployeeService {
public Page<EmployeeDTO> findAll(PageRequest pageRequest) {
Page<Employee> employees = repository.findAll(pageRequest); // ok
Page<EmployeeDTO> dtos = employees.map(emp -> mapper.toDTO(emp, new CycleAvoidMappingContext()); // this is where the exception happens
return dtos;
}
}
// also there is EmployeeDTO and RoleDTO classes mirroring the entity classes
// and there is a simple interface EmployeeMapper loaded as a spring component
// without any special mappings. However CycleAvoidingMappingContext is used.
I have tracked down the LazyInitializationException
to happen when the mapper tries to map the roles dependency. The Role
object do have Set<Employee>
and therefore there is a cyclic reference.
When using FetchType.EAGER
new CycleAvoidingMappingContext()
solved this problem, but with LAZY
this no longer works.
Does anybody know how I can avoid the exception and at the same time get my DTOs mapped correctly?