Извлечение сущности, сопоставленное JoinColumns с аннотацией LazyNoProxy, не работающей с критерием запроса, что приводит к n + запросам - PullRequest
0 голосов
/ 07 января 2019

У нас есть одна сущность Film, которая имеет различные сопоставленные сущности Producer, MainActor, которые все загружаются лениво, и сущность BiggestStar, лениво загружаемая и присоединяемая с помощью аннотации @JoinColumns в двух разных столбцах FirstName и LastName без внешнего ключа.

public class Film implements PersistentAttributeInterceptable {
   private PersistentAttributeInterceptor interceptor;

   @OneToOne(fetch = FetchType.LAZY, mappedBy = "film")
   @LazyToOne(LazyToOneOption.NO_PROXY)
   @LazyGroup("producer")
   public Producer getProducer() {
       return producer;
   }

   @ManyToOne(fetch = FetchType.LAZY)
   @NotFound(action = NotFoundAction.IGNORE)
   @JoinColumns(foreignKey = @javax.persistence.ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT),
    value = {@JoinColumn(name = "starFirstName", referencedColumnName = "firstName", insertable = false, updatable = false),
        @JoinColumn(name = "starLastName", referencedColumnName = "lastName", insertable = false, updatable = false)})
   @LazyToOne(LazyToOneOption.NO_PROXY)
   @LazyGroup("biggestStar")
   public BiggestStar biggestStar() {
       if (interceptor != null) {
           return (F) interceptor.readObject(this, "biggestStar", biggestStar);
       }
       return biggestStar;
   } 
}

У меня есть один критерий запроса, в котором я хочу получить сущность Film и получить продюсера BiggestStar, но не MainActor.

CriteriaQuery<Film> query = cb.createQuery(Film.class);
Root<Film> root= query.from(Film.class);
root.fetch(Film_.producer, JoinType.LEFT);
root.fetch(Film_.biggestStar, JoinType.LEFT);
query.select(root).where(...)

теперь, если я выполню этот запрос, я получу только один зарегистрированный оператор SQL, который точно выбирает все мои объекты, и я получу все значения для таблиц Film, Producer и BiggestStar но когда вызывается метод получения на film.getBiggestStar(), выдается другое утверждение, выбирающее столбцы соединения в таблице фильмов. При проверке объекта фильма самое большое звёздное значение равно нулю до тех пор, пока вы не выполните getBiggestStar (), но затем не выдает другую команду для таблицы самого большого звёздного, а только для таблицы фильмов.

как

select starFirstName, starLastName from Film

В результате n + 1 запросов, поскольку я использую этот запрос для извлечения данных для таблицы.

Я не знаю, что я делаю здесь неправильно, как я могу добиться быстрой выборки всех этих объектов в одном запросе, сохраняя ленивую загрузку.

некоторые оговорки:

  • Я знаю, что мог бы использовать собственный SQL
  • У меня нет доступа к базе данных, поэтому я не могу добавлять внешние ключи или улучшать схему данных
  • база данных Oracle 12
...