Spring, JPA и Hibernate несколько запросов, выполненных из одного оператора SQL

1

Я совершенно не знаком с Spring, JPA и Hibernate, поэтому извиняюсь, если я не правильно ставил этот вопрос.

Мне было предоставлено приложение, использующее эти фреймворки с несколькими проблемами производительности.

Я сделал многочисленные поиски безрезультатно - возможно, из-за моей неспособности правильно сформулировать мой вопрос.

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

Надуманным примером может быть:

public class Job
{
    public long jobId;
    public String name;
    public List<Transaction> transactions;
} 
public class Transaction
{
    public long transactionId
    public List<Stock> stocks;
}
public class Stock
{
    public long stockId;
    public String name; 
}

The code uses a statement like:
String jpaQuery = "select distinct j from Job j where j.jobId = :jobId order by name asc";
Query query = entityManager.createQuery(jpaQuery);
//set parameters...

//This will return a List<Job>, containing lists of Transaction and Stock objects 
return query.getResultList();

Выполнение этого одиночного оператора sql приводит к выполнению нескольких выполняемых sql-операторов (которые можно просмотреть в консоли журнала tomcat/eclipse), поэтому они вызываются кодом/каркасом. EntityManager не был расширен, поэтому структура выполняет работу.

Теперь мой вопрос - спасибо за прочтение этого...

В Spring, JPA и Hibernate, каким будет лучший способ приблизиться к этому, так что один вызов в базу данных возвращает требуемые объекты без нескольких запросов к базе данных?

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

Я не знаю, как это сделать в среде Spring/JPA/Hibernate. Может ли кто-нибудь указать мне на ресурсы, которые дадут мне примеры/идеи о том, как подойти к этому? Или ключевые слова для поиска?

Версия: Spring: 3.0.6.Отмена Hibernate: 3.5.0-Beta-2

Большое спасибо Стив

  • 0
    Вы можете уменьшить это до трех запросов с помощью кэша второго уровня Hibernates ( baeldung.com/hibernate-second-level-cache ). Сначала вы запросите акции, затем запросите транзакции, а затем запросите работу. Это будет зависеть от вашей способности создать один запрос для получения всех требуемых Акций и один запрос для получения всех требуемых Транзакций. Кэш второго уровня предотвратит отдельные запросы для каждой акции и транзакции, так как Hibernate будет уже кэшировать эти объекты и не должен будет вызывать запрос.
Теги:
spring
hibernate
jpa
one-to-many

1 ответ

1
Лучший ответ

Во-первых, это не оператор SQL, это оператор JPQL, который представляет собой огромную разницу (не синтаксис, а логический мудрый).
Во-вторых, причиной множественных операторов SQL является "один-ко-многим" отношениям с заданием на транзакцию на акции (это называется проблемой N + 1). В зависимости от вашего варианта использования вы можете изменить отношения к ленивой загрузке. Это означает, что они загружаются только тогда, когда вам нужны объекты. Однако это может вызвать другие проблемы, если они не обрабатываются правильно. Вы также можете попытаться использовать функцию "Взятие". Это создаст единый запрос с соединением, вместо этого выдает один подсегмент для каждого элемента в коллекции.

  • 0
    Спасибо Данни за быстрый ответ и разъяснения. Все объекты должны быть загружены за один раз. Я буду проверять ссылки, конечно же, присоединение к сборке выглядит как путь, как только я разбираюсь в синтаксисе.
  • 0
    У меня похожая проблема. Все внешние строки (я использую @OneToOne и @OneToMany в нескольких местах) явно (каждая отдельно) загружаются с помощью SQL-запроса с помощью WHERE . Интересно, как я могу избавиться от этого утверждения WHERE? Я знаю FetchMode.LAZY но это только задержит проблему, пока ваша пользовательская база не увеличится. В настоящее время я использую по умолчанию ( EAGER ). Любой способ сказать JPA (только javax.persistence.* Используется здесь), чтобы получить всю таблицу? ОЗУ не проблема, но производительность может быть.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню