JPA загружает слишком много данных, даже если fetchtype ленив

У меня есть приложение, которое загружает данные, относящиеся к канализационной сети. Вот образец вовлеченных лиц. Сначала я определяю сущность Network:

@Entity
@Table(name = "network")
public class Network extends Serializable {
  @Id
  @generatedValue(strategy=GenerationType.AUTO)
  private Long id;

  ...
  @OneToMany(mappedBy = "network")
  private List<Conduit> conduits;

  @OneToMany(mappedBy = "network")
  private List<ConduitVolumeter> conduitVolumeters;

  ...
}

Второй задействованный объект - это Conduit, представляющий канал в сети.

@Entity
@Table(name = "conduit")
@NamedQuery(name = "Conduit.findAll", query = "SELECT c FROM Conduit c")
public class Conduit extends Serializable {
  @Id
  @generatedValue(strategy=GenerationType.AUTO)
  private Long id;

  ...
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "id_network", nullable = false)
  private Network network;

  @OneToOne(mappedBy = "conduit", fetch = FetchType.LAZY)
  private ConduitVolumeter conduitVolumeter;

  ...
}

Далее я определяю ConduitVolumeter. Он представляет собой измерительное устройство, используемое для измерения объема в трубопроводе. Поскольку объемы могут быть измерены в других сетевых элементах, существует абстрактный класс Volumeter, связанный с таблицей volumeter в базе данных.

@Entity(name = "ConduitVolumeter")
@DiscriminatorValue("1")
public class ConduitVolumeter extends Volumeter {

  @OneToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "id_nme")
  private Conduit conduit;

  ...
}

@Entity
@Table(name = "volumeter")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "nme_type", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Volumeter extends Serializable {
  @Id
  @generatedValue(strategy=GenerationType.AUTO)
  private Long id;

  ...
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "id_network", nullable = false)
  private Network network;

  ...
}

Проблема в том, что когда я пытаюсь загрузить все каналы, связанные с сетью, Hibernate пытается систематически загружать каждый томомер, связанный с каждым загруженным каналом, по одному, в соответствии с его журналами.

Hibernate: 
    select
        conduit0_.id as id_1_7_,
        conduit0_.name as name23_7_,
        conduit0_.id_network as id_netw39_7_,
    from
        conduit conduit0_ cross 
    join
        network network1_ 
    where
        conduit0_.id_network=?

...

Hibernate: 
    select
        conduitvol0_.id as id2_116_0_,
        conduitvol0_.name as name10_116_0_,
        conduitvol0_.id_network as id_netw15_116_0_,
        conduitvol0_.id_nme as id_nme17_116_0_ 
    from
        volumeter conduitvol0_ 
    where
        conduitvol0_.id_nme=? 
        and conduitvol0_.nme_type=1

Мой вопрос: почему Hibernate пытается загрузить данные томомера? Каждая аннотация @ManyToOne и @OneToOne устанавливается с помощью FetchType.LAZY. Что я упустил?

Кстати, меня просят использовать JPA с устаревшей базой данных. Проблема в модели базы данных? Есть ли способ загрузить кабелепроводы без измерителей объема?

С Уважением.

Франсуа

Всегда помните, что отложенная загрузка - это намек, а не гарантия.

chrylis -cautiouslyoptimistic- 08.06.2018 16:03
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
395
1

Ответы 1

FetchType - это всего лишь подсказка. Это зависит от того, как вы запрашиваете данные, если вы используете методы репозитория spring-data-jpa, такие как методы findOne или findBy (производные запросы), тогда Lazy должен работать, но если вы используете репозиторий JPA с @Query в методе репозитория и напишите ваш запрос, то Lazy может не работать.

Спасибо за этот ответ. Я попробую. По сути, я использую запрос в репозитории каналов. Я попробую использовать один из методов findBy, чтобы проверить ваш ответ.

Francois 08.06.2018 16:35

Я попытался использовать метод репозитория spring-jpa-data findByNetwork из репозитория каналов. Ничего не меняется. Он загружает объемные метры, как раньше.

Francois 08.06.2018 16:52

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