Псевдоним гибернации - нормально ли все еще делать n + 1? - PullRequest
1 голос
/ 12 сентября 2011

У меня есть очень специфический вопрос из двух частей, который я действительно очень надеюсь, что раньше его не задавали:)

Сначала контекст

У меня есть несколько компонентов Hibernate с ленивыми ассоциациями между нимитакие как:

@Entity
public class SalesData {

   @ManyToOne(optional = false, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
   @JoinColumn(nullable = false)
   public Product getProduct() {
     return product;
   }

}

, а затем:

@Entity
public class Product {

  @OneToMany(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  public Set<SoundRecording> getSoundRecordings() {
    return soundRecordings;
  }

}

и, наконец,

@Entity public class SoundRecording {
}

Теперь, если я сделаю запрос Criteria, где я добавлю псевдонимы дляОтношение SalesData к Product, а затем для Product to SoundRecording, например:

Criteria criteria = session.createCriteria(SalesData.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.createAlias("product", "p");
criteria.createAlias("p.soundRecordings", "s");

Я вижу в журнале Hibernate, что он генерирует SQL, например:

select ... from SalesData this_ 
inner join Product p1_ on this_.product_id=p1_.id 
    inner join SoundRecording s5_ on p1_.id=s5_.product_id 
        where ...

, когда я вызываю критерии.list () именно то, что я хочуОднако, если я сделаю:

salesDatas.getProduct().getSoundRecordings(0);

, в журнале я вижу, что Hibernate сделал еще один конкретный запрос выбора SQL, чтобы восстановить эту связь:

select ... from SoundRecording soundrecor0_ where soundrecor0_.product_id=?

Тогда мой вопрос:

Это нормально?Моя цель здесь - загрузить одним выстрелом (одним SQL-запросом) все, что мне нужно, чтобы избежать этих n + 1 выборов.Я думал, что использование псевдонима - один из способов сделать это, тем более что я ясно вижу, что его генерирует внутреннее соединение между таблицами.Если я использую explictit fetchMode (Join), то hibernate не будет выдавать все дополнительные выборки, он будет удовлетворен первоначальным выбором со многими (внешними) объединениями.Почему же это не относится к объединениям, генерируемым псевдонимами?

1 Ответ

2 голосов
/ 12 сентября 2011

Псевдоним или подкритерий используется для создания объединения. Это объединение может иметь две цели:

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

Если вы хотите 1 и не хотите 2, то выборка не нужна, и поэтому вы не должны вызывать setFetchMode()). Если вы хотите 2, то выборка необходима.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...