Как настроить запросы гибернации

#java #database #hibernate #spring

#java #База данных #гибернация #spring

Вопрос:

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

Проблема, которую мы наблюдаем, заключается в том, что веб-приложению требуется неприлично много времени для загрузки страниц (с использованием JSP, Spring и Hibernate).

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

Есть ли способ настроить запросы гибернации так, чтобы они не использовали эту формулу в запросе (кроме значения столбца)? Пожалуйста, сообщите, если вам требуется дополнительная информация.

Редактировать: Согласно запросу, вот запрос, который я получил при регистрации в режиме гибернации:

 SELECT this_.PARTY_ID       AS PARTY1_23_2_,
  this_.STUDENT_ID          AS STUDENT3_23_2_,
  this_.STUDENT_PIDM        AS STUDENT4_23_2_,
  this_.USERNAME            AS USERNAME23_2_,
  this_.FIRST_NAME          AS FIRST6_23_2_,
  this_.LAST_NAME           AS LAST7_23_2_,
  this_.ACTIVE              AS ACTIVE23_2_,
  subjectenr1_.PARTY_ID     AS PARTY1_24_0_,
  subjectenr1_.OFFERING_ID  AS OFFERING2_24_0_,
  subjectenr1_.RSTS_CODE    AS RSTS3_24_0_,
  subjectenr1_.SITE_CODE    AS SITE4_24_0_,
  subjectenr1_.PROGRAM_CODE AS PROGRAM5_24_0_,
  (SELECT su2.offering_id
  FROM sakaicfg.subject_offering su2
  WHERE su2.offering_id = subjectenr1_.OFFERING_ID
  )                               AS formula0_0_,
  subjectoff2_.OFFERING_ID        AS OFFERING1_25_1_,
  subjectoff2_.CRN                AS CRN25_1_,
  subjectoff2_.IS_ACTIVE          AS IS3_25_1_,
  subjectoff2_.TEACHING_SCHOOL    AS TEACHING4_25_1_,
  subjectoff2_.CAMPUS             AS CAMPUS25_1_,
  subjectoff2_.START_SEMESTER     AS START6_25_1_,
  subjectoff2_.STUDYMODE          AS STUDYMODE25_1_,
  subjectoff2_.SUBJECT_ID         AS SUBJECT8_25_1_,
  subjectoff2_.GRADE_MARKING_CODE AS GRADE9_25_1_,
  (SELECT MAX(su2.effective_semester)
  FROM sakaicfg.subject su2
  WHERE su2.subject_id        = subjectoff2_.SUBJECT_ID
  AND su2.effective_semester <= subjectoff2_.START_SEMESTER
  ) AS formula1_1_
FROM SAKAICFG.STUDENT this_
INNER JOIN SAKAICFG.SUBJECT_ENROLMENT subjectenr1_
ON this_.PARTY_ID=subjectenr1_.PARTY_ID
INNER JOIN SAKAICFG.SUBJECT_OFFERING subjectoff2_
ON (SELECT su2.offering_id
  FROM sakaicfg.subject_offering su2
  WHERE su2.offering_id     = subjectenr1_.OFFERING_ID)=subjectoff2_.OFFERING_ID
WHERE this_.ACTIVE          ='Y'
AND subjectenr1_.RSTS_CODE <>'DD'
AND subjectoff2_.IS_ACTIVE  ='Y'
AND subjectoff2_.OFFERING_ID='35505'
ORDER BY this_.PARTY_ID DESC;
  

Часть, о которой идет речь, — это выдержка:

   (SELECT su2.offering_id
  FROM sakaicfg.subject_offering su2
  WHERE su2.offering_id = subjectenr1_.OFFERING_ID
  )
  

Сопоставляющий XML-файл для таблицы регистрации субъекта содержит следующие взаимосвязи:

 <many-to-one name="student" entity-name="CsuActiveStudentDto" column="PARTY_ID" insert="false" update="false" access="field" unique="false"/>
<many-to-one name="subjectOffering" entity-name="CsuSubjectOfferingDto" insert="false" update="false" access="field" unique="false">
   <formula>(select su2.offering_id
            from sakaicfg.subject_offering su2 where su2.offering_id = OFFERING_ID)</formula>
</many-to-one>
<one-to-one name="student" class="au.edu.csu.enterprise.domain.StudentDto" property-ref="enrolment"/>
<many-to-one name="offering" class="au.edu.csu.enterprise.domain.SubjectOfferingDto" column="OFFERING_ID"/>
  

Я работал с одним из наших администраторов базы данных, просматривая запросы и выделяя те, на которые нужно обратить внимание, вот как мы нашли этот.

Комментарии:

1. может помочь, если вы приведете пример или даже реальный запрос, если он не слишком длинный.

2. Запросы Hib могут быть оптимизированы практически так же, как и SQL-запросы; поэтому поставленная перед вами задача, безусловно, выполнима. Но вам нужно было бы показать код.

Ответ №1:

Вы можете переопределить инструкции Hibernate Create Read Update и Delete с помощью пользовательского SQL (не hql) для каждого объекта (и коллекций тоже).

Для получения более подробной информации взгляните на ссылку на Hibernate: Глава 17.3. Пользовательский SQL для создания, обновления и удаления и о том, как это работает в справочнике аннотаций Hibernate: Глава 2.4.10. Пользовательский SQL для операций CRUD

 @Entity
@SQLInsert( sql="INSERT INTO Demo(name, id) VALUES(?,?)")
@Loader(namedQuery = "betterLoad")
@NamedNativeQuery(name="betterLoad",
        query="select id, name from Demo where id= ?",
        resultClass = Demo.class)
public class Demo {
    @Id
    private Long id;
    private String name;
}