0

У меня есть некоторые трудности с Spring и Hibernate и ленивая загрузка. Есть много вопросов и ответов, но не совсем то, что я ищу.Hibernate Spring JPA нагрузка только конкретные ленивые отношения

Так что скажем, у меня есть класс . С id, name и от одного до многих отношений с doors, windows и wheels. Поскольку они являются oneToMany, они по умолчанию ленивы загружаются, что является предпочтительным, потому что, когда я хочу посмотреть имя car, я не хочу видеть шины и прочее. Это работает в моем случае, используя методы findOne() моих репозиториев.

Но когда я хочу посмотреть давление в шинах, мне нужно инициализировать отношения tires. Раньше я делал это с Hibernate.initialize(car.getTires()). Это вызывает другой запрос SELECT для базы данных. Теперь я хочу улучшить свои запросы к базе данных и выбрать только car с tires, но оставьте windows и doors. (Что возможно в MySQL с объединениями). Возможность заставить их загружать нетерпимость не может быть и речи, потому что я не всегда хочу загрузить связь tires (у меня есть некоторые большие отношения на моих объектах).

Я попробовал следующий подход:

@Query("SELECT c FROM Car c JOIN FETCH c.tires WHERE c.id = :id") 
Car findOneWithTiresLoaded(@Param("id") Long id); 

Это обеспечит правильные данные. Но после анализа объекта, возвращенного из репозитория, я заметил, что все отношения загружены. Таким образом, это не только возвращает car с отношением tires, но также и doors и windows. Ниже дает мне тот же результат (с соотношением moneToMany загруженного)

@Query("SELECT c FROM Car c WHERE id = :id") 
Car findOneWithTiresLoaded(@Param("id") Long id); 

Что-то, что не хотело. Я ожидал, что это приведет только к объекту Car без всех его ленивых отношений.

Также предлагается людьми в Интернете, чтобы позвонить по телефону Car.getTires().size(). Который также произведет еще один запрос SELECT.

Есть ли способ просто выбрать Car только с грузом Tires? Без fetch = FetchType.LAZY, Hibernate.initialize() или size() метод? Как невозможно просто присоединиться к одной таблице? Кроме того, я не использую XML для любой конфигурации.

Спасибо!

ответ

1

Я бы всегда предлагал реализовать это, используя диаграммы сущностей. Я приведу пример с использованием Spring Data. Также следует всегда использовать ленивую загрузку, независимо от того, какие другие отношения можно объединить с помощью определенных графиков.

Таким образом, вы можете быть очень конкретны в своих запросах и ТОЛЬКО получать данные, необходимые для вашей бизнес-логики. Вы даже можете определить субграфы, чтобы показать, что вы хотите выбрать из tires объектов. Это означало бы, что у вас всегда есть ленивые выборки во всех отношениях объекта Tire. По умолчанию все, что вы получаете, это tires (по запросу) и никаких других отношений от них. Если вы также хотите что-нибудь еще от tires, то вам остается только определить другой набор определений графов и ссылаться на них из вашего репозитория, где вы делаете запрос в виде подграфов.

@Entity 
@Table(name = "car") 
@NamedEntityGraph(name = Car.TIRES_GRAPH, attributeNodes = @NamedAttributeNode("tires")) 
public class Car { 

    public static final String TIRES_GRAPH = "Car.tires"; 

    @OneToMany(mappedBy = "car", fetch = FetchType.LAZY} 
    private Set<Tire> tires = new HashSet<>(); 

} 

И для вашего хранилища, вы можете иметь метод

@Query("SELECT c FROM Car c") 
@EntityGraph(Car.TIRES_GRAPH) 
Set<Car> findAllWithTires(); 

Даже если вы не используете Spring Data, то подход такой же, и вы можете легко найти хорошие примеры этого.

EDIT

Другой проверенный рабочий пример. Просто убедитесь, что имена полей соответствуют домену Spring Data для их устранения.

public interface CarRepository extends JpaRepository<Car, Long> { 

    @EntityGraph(attributePaths = { "tires" }) 
    Set<Car> findAllWithTiresByCarId(Long id) 
} 

Link документации

+0

мне нужно аннотировать Entity с '@ Table' аннотацию делать? Поскольку мы не делаем этого прямо сейчас, и если его не нужно, было бы чище не писать его. Или он используется с графами объектов? Я попробую это сейчас. Я буду отмечать ваш ответ как решение, если это сработает для нас. Спасибо за ответ! – Clemenz

+0

Отсутствие '@ Table' может быть опущено, я просто использовал его для определения объектов. – Vaelyr

+0

Я только что открыл класс 'Car' расширяет класс' Vehicle'. И поэтому он использует аннотации '@ Inheritance'. (Также аннотация @DiscriminatorValue ('автомобиль'). Когда я пытаюсь использовать именованный график в элементе 'Car', он вызывает ошибку при загрузке. 'Невозможно найти атрибут с заданным именем [Tires] в этом ManagedType [com.example.domain.Vehicle]'. Но я запрашиваю таблицу 'Car' в репозитории' Car'. Что может быть причиной этого? – Clemenz

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

  • Нет связанных вопросов^_^