2015-01-06 2 views
1

У меня есть эти классы:Hibernate создания ненужных запросов для @ManyToOne аннотированный недвижимости

@Entity 
public class Invoice implements Serializable { 
    @Id 
    @Basic(optional = false) 
    private Integer number; 

    private BigDecimal value; 

    //Getters and setters 
} 

@Entity 
public class InvoiceItem implements Serializable { 
    @EmbeddedId 
    protected InvoiceItemPK invoiceItemPk; 

    @ManyToOne 
    @JoinColumn(name = "invoice_number", insertable = false, updatable = false) 
    private Invoice invoice; 

    //Getters and setters 
} 

Когда я запустить этот запрос:

session.createQuery("select i from InvoiceItem i").list(); 

Он выполняет один запрос для выбора записей из InvoiceItem, и если У меня есть 10000 элементов счета, он генерирует 10000 дополнительных запросов, чтобы выбрать Счет-фактуру из каждого InvoiceItem. Я думаю, было бы намного лучше, если бы все записи могли быть получены в одном sql. На самом деле я нахожу это странным, почему это не поведение по умолчанию.

Итак, как я могу это сделать?

ответ

1

Попробуйте с

session.createQuery("select i from InvoiceItem i join fetch i.invoice inv").list(); 

Он должен получить все данные в одном запросе SQL с помощью соединения.

+0

Ну, на самом деле это нормально работает, но есть ли способ сделать это, используя аннотации? Потому что, допустим, у нас есть много аннотированных полей @ManyToOne, я не хочу писать много JOIN FETCH XXX, чтобы избежать проблемы ... –

+1

Hibernate имеет аннотацию '@ Fetch', которую вы можете использовать, @Fetch (FetchMode.JOIN) 'на вашем сопоставлении отношений. –

+0

Даже используя '@Fetch (FetchMode.JOIN)' он по-прежнему создает дополнительные запросы. Полагаю, мне придется работать с исправлением запроса. –

-1

В этом методе запускаются несколько SQL-запросов. Этот первый запускается для извлечения всех записей в родительской таблице. Оставшиеся увольняются для получения записей для каждой родительской записи. Первый запрос извлекает M записей из базы данных, в этом случае записи M Parent. Для каждого родителя новый запрос возвращает Child.

+1

Да, я уже знаю это. Вопрос состоял в том, как избежать этого. –

0

Да, есть необходимые настройки: @BatchSize(size=25). Проверьте это здесь:

20.1.5. Using batch fetching

небольших процитировать:

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

Пакетная выборка для классов/понятий проще понять. Рассмотрим следующий пример: во время выполнения у вас есть 25 экземпляров Cat, загруженных в сеанс, и каждый Cat имеет ссылку на своего владельца - Person. Класс Person сопоставляется с прокси-сервером, lazy = "true". Если вы теперь перебираете всех кошек и вызываете getOwner() на каждом, Hibernate по умолчанию выполнит 25 операторов SELECT для извлечения доверенных владельцев. Вы можете настроить это поведение, определяя пакетный размер в отображении Person:

<class name="Person" batch-size="10">...</class> 

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

Таким образом, мы можем использовать эту аннотацию как:

  • коллекции/наборы
  • классы/Entities

Проверьте это также здесь:

Смежные вопросы