2016-08-04 3 views
2

У нас есть несколько объектов с кучей свойств, аннотированных аннотацией Hibernate @Formula. Фрагменты SQL в аннотации в основном выполняют скалярные подзапросы (например, COUNT запросов). В качестве примера у нас есть иерархия отношений «один ко многим», которая имеет четыре уровня: A <- B <- C <- D (где <- обозначает связь «один-ко-многим»). Довольно часто при получении объекта типа A мы хотели бы знать количество связанных объектов типа D. Для этого мы используем @Formula -необходимое свойство в A.Управление ленивой/нетерпеливой загрузкой столбцов @Formula динамически

Поскольку мы не нуждаемся в этих значениях каждый раз, мы объявили свойства @Formula ленивыми (мы включили поддержку байт-кода Hibernate, чтобы сделать это возможным). Но для некоторых запросов мы хотели бы загрузить эти свойства с нетерпением. Мы часто загружаем сотни объектов типа A в одном запросе, и было бы важно, чтобы управлять динамической загрузкой этих свойств с нетерпением/ленивом. Мы уже используем графики сущностей JPA, чтобы контролировать, какие свойства загружаются с нетерпением для определенных запросов, но диаграммы сущностей, похоже, не работают здесь. Даже если мы перечислим свойства @Formula в графе сущности, они все еще загружаются лениво.

Возможно ли контролировать динамическую загрузку столбцов в @Formula столбцами за каждый запрос? В настоящее время мы ограничены API запросов к критериям JPA, и названные запросы здесь не являются возможностью.

Update:

Свойства в вопросе не являются ассоциации с другими лицами, но только некоторые расчетные значения. Это означает, что, например, fetch профили здесь не применяются, поскольку они применимы только к ассоциациям сущностей (или, по крайней мере, так я понял Hibernate manual). Вот пример одного из наших @Formula свойств:

@Entity 
public class A { 

    @Basic(fetch = FetchType.LAZY) 
    @Formula("(select count(*) from entity_D_table where ...)") 
    private int associatedDCount; 

    ... 
} 

ответ

0

Вы можете попытаться взглянуть на Hibernate в извлекающих профилях https://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch20.html#performance-fetching-profiles.

Вы можете, например, аннотировать объект, как этот

@Entity 
@FetchProfile(name = "country_states", fetchOverrides = { 
      @FetchProfile.FetchOverride(entity = Country.class, association = "states", mode = FetchMode.JOIN) 
}) 
public class Country implements Serializable {... 

и активировать режим РЕГИСТРИРУЙТЕСЬ при запросе, например:

session=getSession(); 
session.beginTransaction(); 
//enable fetch profile for EAGER fetching 
session.enableFetchProfile("country_states"); 

Как показано в http://www.concretepage.com/hibernate/fetchprofile_hibernate_annotation

+0

Но не являются ли профили выборки применимыми только к ассоциациям сущностей? Я добавил пример кода, как выглядят наши свойства, я не думаю, что профили извлечения будут работать здесь. –

+0

Вы правы. Не могли бы вы рассмотреть возможность определения представления SQL в вашей базе данных и сопоставление нового объекта на нем, чтобы получить формулу с нетерпением как простое свойство? –

+0

Я рассматриваю возможность создания представления, но для этого потребуется довольно много изменений в кодовой базе. В настоящее время мы используем графики сущностей JPA, чтобы с нетерпением загружать данные из десятков таблиц за один раз, и код ожидает, что он получит весь граф объекта. Но если нынешний подход окажется слишком медленным в бенчмаркинге, нам придется подумать об этом еще раз. –

1

Вы можете использовать Critria api, чтобы он возвращал DTO вместо Entity.

В запросе критериев используйте Projection для выбора только нужного столбца.

ProjectionList properties = Projections.projectionList(); 
properties.add(Projections.property("id").as("id")); 
properties.add(Projections.property("name").as("name")); 
properties.add(Projections.property("lazyField").as("lazyField")); 
criteria.setProjection(properties); 
criteria.setResultTransformer(new AliasToBeanResultTransformer(MyEntityDTO.class)); 

Таким образом, запрос выбора будет содержать только те поля, которые вы задаете, независимо от отображения EAGER или LAZY.

+0

Мы не используем API-интерфейс Hibernate's Criteria, но я бы предположил, что это можно реализовать с помощью API запросов запросов JPA. Это потребует значительных изменений в нашей текущей кодовой базе, но может стоить того, если текущая реализация считается замедленной. На самом деле не решает проблемы, но +1 для идеи в любом случае. –

+0

Из моего опыта использования DTO вместо Entity лучше для производительности, когда мне просто нужно отображать данные: у вас есть контроль над количеством соединений или столбцом и вы можете создать определенный индекс для ускорения запросов еще больше – jpprade

+0

Ну, количество объединений можно контролировать с помощью графиков сущностей JPA, и я понимаю, что выборки слишком большого количества столбцов не должны быть такими большими, как при ударе производительности. Но да, использование DTO, как вы описали, позволяет больше контролировать и настраивать. По крайней мере, в нашем случае, это также потребует большей работы по внедрению и увеличивает сложность кода, и я не знаю, является ли это хорошим компромиссом. –

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