Ленивая загрузка JPA не работает при загрузке Spring

Я много гуглил, и это действительно странно, что Spring Boot (последняя версия) может не иметь ленивой загрузки, которая не работает. Ниже приведены фрагменты моего кода:

Мой ресурс:

 public ResponseEntity<Page<AirWaybill>> searchAirWaybill(CriteraDto criteriaDto, @PageableDefault(size = 10) Pageable pageable{
airWaybillService.searchAirWaybill(criteriaDto, pageable);
        return ResponseEntity.ok().body(result);
}

Мой сервис:

@Service
@Transactional
public class AirWaybillService {

//Methods

 public Page<AirWaybill> searchAirWaybill(AirWaybillCriteriaDto searchCriteria, Pageable pageable){
    //Construct the specification
            return airWaybillRepository.findAll(spec, pageable);
   }
}

Моя сущность:

@Entity
@Table(name = "TRACKING_AIR_WAYBILL")
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property = "@airWaybillId") //to fix Infinite recursion with LoadedAirWaybill class
public class AirWaybill{
//Some attributes
    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FK_TRACKING_CORPORATE_BRANCH_ID")
    private CorporateBranch corporateBranch;
}

И при отладке я все еще получаю все ленивые загруженные атрибуты загруженных. См. изображение ниже.

Ленивая загрузка JPA не работает при загрузке Spring

Один из моих вопросов: мог ли Джексон быть причастен к такому поведению? Есть ли способ, которым я мог пропустить, чтобы активировать ленивую загрузку?

РЕДАКТИРОВАТЬ

Еще вопрос, мог ли отладчик быть причастен к испорченной ленивой загрузке?

Обновлено еще раз:

Для сборки Технические характеристики у меня есть:

public static Specification<AirWaybill> isBranchAirWayBill(long id){
    return new Specification<AirWaybill>() {
        @Override
        public Predicate toPredicate(Root<AirWaybill> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            return cb.equal(root.join("corporateBranch",JoinType.LEFT).get("id"),id);
        }
    };
}

где настроен транзакционный? на ресурсе или сервисе?

Maciej Kowalski 16.04.2019 09:30

На службе. я обновил вопрос

Houssem Badri 16.04.2019 09:32

Есть ли в ваших критериях какие-либо условия для CorporateBranch? Если да, то как вы создаете спецификацию, переданную в репозиторий?

Lesiak 16.04.2019 10:04

Да, но условно и даже я убрал спецификацию и загрузил только страницу но все равно вижу проблему

Houssem Badri 16.04.2019 10:17

Просто чтобы отбросить проблему, связанную с отладчиком, включите ведение журнала SQL-запросов Spring Boot: stackoverflow.com/questions/30118683/…

Xtreme Biker 16.04.2019 11:27
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
13
5
27 920
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

При использовании отладчика вы пытаетесь получить доступ к значению ваших переменных. Итак, в тот момент, когда вы нажимаете на эту маленькую стрелку на экране, значение рассматриваемой переменной (лениво) загружается.

Спасибо. Но еще до того, как я нажму на стрелку, я вижу в строке того атрибута, в котором уже есть информация

Houssem Badri 16.04.2019 09:38

IDE обрабатывают отладку по-разному. InteliJ загружает для вас все заранее, а другая IDE может и нет.

Sofo Gial 16.04.2019 09:40

Скорее всего, вы отлаживаете, все еще находясь внутри службы, поэтому, пока транзакция все еще активна, может быть запущена ленивая загрузка (любой метод, вызванный для ленивого элемента, инициировал выборку из базы данных).

Проблема в том, что отложенная загрузка не может происходить вне транзакции. И Джексон анализирует вашу сущность определенно за пределами одной.

Вы должны либо получить все необходимые зависимости при создании спецификации, либо попробовать использовать @Transactional на уровне ресурсов (но попробуйте это в крайнем случае).

Просто чтобы вы знали, стратегия ЛЕНИВОЙ выборки — это всего лишь подсказка, а не обязательное действие. Стремление обязательно:

The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified.

Даже когда я вижу ответ в своем браузере, я вижу, что все лениво загруженные атрибуты загружены (что мне не нравится). Так что отладчик не имеет ничего общего с загруженными дочерними элементами.

Houssem Badri 16.04.2019 09:44

проверьте мое обновление.

Maciej Kowalski 16.04.2019 09:50

Просто предположение: вы форсируете выборку при построении спецификации.

Я ожидаю что-то вроде

static Specification<AirWaybill> buildSpec() {
    return (root, query, criteriaBuilder) -> {
       Join<AirWaybill, CorporateBranch> br = (Join) root.fetch("corporateBranch");
       return criteriaBuilder.equal(br.get("addressType"), 1);
    };
}

Если это так, попробуйте изменить root.fetch на root.join

Спасибо за ваше уведомление, пожалуйста, смотрите обновленное выше

Houssem Badri 16.04.2019 10:49

SpringBoot по умолчанию включил:
spring.jpa.open-in-view = правда
Это означает, что транзакция всегда открыта. Попробуйте отключить его.
дополнительная информация здесь

Хорошая помощь, теперь я получаю org.hibernate.LazyInitializationException: could not initialize proxy - no Session. Я пытался установить Hibernate5Module, но пока не получилось, все та же ошибка

Houssem Badri 16.04.2019 11:54

Вы можете исправить это с помощью @Transactional. См. ответ Ковальски.

gagarwa 25.06.2020 04:36

Извлеченные данные уже ленивы, но вы используете режим отладки, его возвращаемое значение при нажатии для просмотра данных из отладчика.

добавьте такой ответ в комментарии.

Pratik Bhajankar 16.04.2019 15:21
Ответ принят как подходящий

Сессия гибернации существует в методе с @Transactional. Передача объекта за пределы класса обслуживания — плохая практика, потому что сеанс закрывается после выхода из вашего метода search. С другой стороны, ваша сущность содержит ленивые инициализированные коллекции, которые нельзя извлечь после закрытия сеанса.

Хорошей практикой является сопоставление сущности с транспортным объектом и возврат этих транспортных объектов из службы (а не необработанных сущностей).

точно лаконично и понятно

Houssem Badri 17.04.2019 08:20

Извините, но я этого не понимаю. У вас есть пример, показывающий, как настроен этот транспортный дизайн? заранее спасибо

Alex 20.09.2019 15:17

Пожалуйста, создайте простой POJO (скажем, AirWaybillTO и поместите туда все необходимые атрибуты, затем сопоставьте их с AirWaybill и верните AirWaybillTO из вашего сервиса.

Tomasz Białecki 25.08.2020 09:44

Вы можете решить эту проблему с помощью 2 шагов с Джексон-тип-данных-спящий режим:

kotlin example

  1. Добавьте build.gradle.kts:
implementation("com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:$jacksonHibernate")
  1. Создать @Bean
   @Bean
   fun hibernate5Module(): Module = Hibernate5Module()

Обратите внимание, что Module — это com.fasterxml.jackson.databind.Module, а не java.util.Module

Я также столкнулся с той же проблемой с данными Spring JPA. Я добавил приведенную ниже аннотацию и смог получить записи о клиентах для данного ИДЕНТИФИКАТОРА ЗАКАЗА.

Клиент для заказа: один ко многим

Заказ клиенту является ленивой загрузкой.

Заказ.java

@ManyToOne(cascade = CascadeType.ALL,targetEntity = CustomerEntity.class,fetch = FetchType.LAZY)
@Fetch(FetchMode. JOIN)
@JoinColumn(name = "CUSTOMER_ID",referencedColumnName = "CUSTOMER_ID",insertable = false,updatable = false)
@LazyToOne(LazyToOneOption.PROXY)
Private CustomerEntity customer

Клиент.java

@Entity
@TabLe(name = "CUSTOMER" ,
uniqueConstraints = @UniqueConstraint(columnNames= {"mobile"}))
public class CustomerEntity {

@GeneratedVaLue(strategy = GenerationType.IDENTITY)
@CoLumn(name = "customer_id" )
private Integer customerld;
private String name;
private String address;
private String city;
private String state;
private Integer zipCode;
private Integer mobileNumber;

@OneToMany(mappedBy = " customer" )
@Fetch(FetchMode.JOIN)
@LazyToOne(LazyToOneOption.PROXY)
private List<OrderEntity> orders;
}

Добавьте код и данные в виде текста (с помощью форматирования кода), а не изображений. Изображения: A) не позволяйте нам копировать и вставлять код/ошибки/данные для тестирования; Б) не разрешать поиск по коду/ошибке/содержимому данных; и еще много причин. Изображения следует использовать в дополнение к тексту в формате кода только в том случае, если изображение добавляет что-то важное, что не передается только текстовым кодом/ошибкой/данными.

Suraj Rao 07.01.2021 12:01

может кто-нибудь объяснить эту аннотацию. в документации это не объяснено должным образом. baeldung.com/hibernate-lazy-loading-обходной путь после прочтения этой статьи кажется, что @ Transactional лучше, но если мы добавим «enable_lazy_load_no_trans», тогда он вызовет список объектов и каждого объекта, на который ссылается ленивый объект, в одной транзакции для каждого объекта. Будет ли @LazyToOne также выполнять одну транзакцию один раз или это всего лишь один дополнительный txn?

Satish Patro 14.01.2021 06:51

Еще одно соображение заключается в том, что при использовании Lombok аннотация @Data/@Getter приводит к загрузке ленивых элементов без необходимости. Так что будьте осторожны при использовании Ломбока.

Это был мой случай.

Другие вопросы по теме