#spring-boot #spring-data-jpa #lazy-loading
Вопрос:
это работает, но когда я пытаюсь удалить courses.size
, я не получаю ошибки сеанса.
@Transactional
public List<Course> initiateCourses(Long id) {
Instructor instructor = instructorRepository.findById(2L).get();
List<Course> courses = instructor.getCourses();
courses.size();
return courses;
}
Это работает, но похоже на халтуру.
также я нашел другой способ загрузки ленивых коллекций.
@Repository
public interface InstructorRepository extends CrudRepository<Instructor, Long> {
@Query("SELECT p FROM Instructor p LEFT JOIN FETCH p.courses WHERE p.id = ?1")
Optional<Instructor> findByIdAndFetchCourseEagerly(Long id);
}
какой из них я должен использовать с точки зрения производительности? или есть лучший способ извлечения ленивых инициализированных объектов.
Комментарии:
1. использование второго подхода-лучший способ. Первый вызовет N 1 проблем с запросами.
Ответ №1:
Вы можете работать с @EntityGraph
тем, чтобы указать, какие части иерархии объектов следует извлекать:
@Repository
public interface InstructorRepository extends CrudRepository<Instructor, Long> {
@EntityGraph(type = EntityGraphType.FETCH, attributePaths = {"courses"})
Optional<Instructor> findById(Long id);
}
Комментарии:
1. спасибо, кэширование также работает в entitygraph?
Ответ №2:
Этот прокси-сервер не будет инициализирован до тех пор, пока вы не извлекете из него элемент или не вызовете size()
метод. Есть несколько способов решить вашу проблему без «магии»:
- Явно вызовите
Hibernate.init()
и передайте в нем свой прокси-сервер коллекции, прежде чем возвращать его из метода. - Используйте диаграмму сущностей, как предложил Питер Уолсер