Hibernate происходит слишком много запросов

Я использую hibernate(с ehcache)/spring/mysql/jsf. Я получаю данные из двух таблиц в mysql. И эти таблицы следующие:
пользователь
id int (первичный ключ)
имя и т. д.
Урок
id int (первичный ключ)
урок варчар
teacher_id int (внешний ключ от пользователя (id))

и класс урока модели:

@Entity
@Table(name = "oys_lesson")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "myregion")
public class Lesson {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;
    @Column(name="lesson")
    private String lessonName;

    @ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
    @JoinColumn(name="teacher_id",nullable=false)
    private User user;
//Getters and Setters

Модель пользователя Класс

@Entity
@Table(name = "oys_user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "myregion")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;
    private String username;
    etc....
    @OneToOne(cascade = CascadeType.REMOVE)
    @JoinTable(name = "oys_user_role", joinColumns = { @JoinColumn(name = "user_id", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "role_id", referencedColumnName = "id") })
    private Role role;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
    private Set<Lesson> teacherLessons;
//Getters and Setters

Я получаю список уроков с этим даоимпл.

public List<Lesson> getLessonList() {
    // TODO Auto-generated method stub
    String username = SecurityContextHolder.getContext()
            .getAuthentication().getName();
    Query query = openSession()
            .createQuery(
                    "from Lesson l where l.user in (select id from User u where u.username=:username)");

    query.setParameter("username", username);
    // query.setCacheable(true);
    List<Lesson> lessonList = query.list();
    if (lessonList.size() > 0)
        return lessonList;
    return null;
}

Этот запрос получает уроки текущего пользователя. Моя jsf страница ниже:

<h:form id="form">
        <p:dataTable var="lesson" value="#{lessonManagedBean.lessonList}"
            paginator="true" rows="10" rowKey="#{lesson.id}"
            paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
            rowsPerPageTemplate="5,10,15" selectionMode="single"
            selection="#{lessonManagedBean.selectedLesson}" id="carTable" lazy="true">
            <p:ajax event="rowSelect" listener="#{lessonManagedBean.onRowSelect}"
                update=":form:lessonDetail" oncomplete="PF('lessonDialog').show()" />
            <p:column headerText="id" sortBy="#{lesson.id}"
                filterBy="#{lesson.id}">
                <h:outputText value="#{lesson.id}" />
            </p:column>
            <p:column headerText="Lesson Name" sortBy="#{lesson.lessonName}"
                filterBy="#{lesson.lessonName}">
                <h:outputText value="#{lesson.lessonName}" />
            </p:column>
        </p:dataTable>

        <p:dialog header="Ders Detayları" widgetVar="lessonDialog" showEffect="fade"
             hideEffect="fade" resizable="false">
            <p:outputPanel id="lessonDetail" style="text-align:center;">
                <p:panelGrid columns="2"
                    rendered="#{not empty lessonManagedBean.selectedLesson}"
                    columnClasses="label,value">

                    <h:outputText value="Id:" />
                    <h:outputText value="#{lessonManagedBean.selectedLesson.id}" />

                    <h:outputText value="Lesson Name" />
                    <h:outputText value="#{lessonManagedBean.selectedLesson.lessonName}" />
                </p:panelGrid>
            </p:outputPanel>
        </p:dialog>
    </h:form>

Когда я открыл эту страницу, я получил следующий вывод в консоли.

Hibernate: выберите lesson0_.id в качестве id0_, lesson0_.lesson в качестве lesson0_, lesson0_.teacher_id в качестве teacher3_0_ из oys_lesson lesson0_, где lesson0_.teacher_id in (выберите user1_.id из oys_user user1_ оставил внешнее объединение oys_user_1 user1__ user_1__ user_1___ user_1__ user_1 пользователя_1 user_1) user1_.username=?)

Когда страница открыта, этот запрос выполняется 3 раза.3 of the same query.Но когда я выбрал row.dialog, открывается окно и запускается тот же запрос. 19 times,

managedBean.class

@ManagedBean
@SessionScoped
public class LessonManagedBean implements Serializable {
    private Lesson selectedLesson=null;
    List<Lesson> lessonList;
//Getters and Setters

Почему выполняется один и тот же запрос несколько раз? Когда открывается диалоговое окно, не нужно выполнять какой-либо запрос? Почему он работает 19 раз? Заранее спасибо..

2 ответа

Решение

Я решил свою проблему.Hibernate выполняет слишком много запросов. Потому что JSF вызывает геттеры несколько раз. Так что мои методы getList работают несколько раз.

Обычно это не рассматривается как серьезная проблема. Поскольку метод получения является очень дешевой операцией.

Но если вы выполняете дорогостоящую бизнес-логику (операцию БД) в методе getter (как и я), это будет выполняться каждый раз. Так что один и тот же запрос (в методе getter) работает снова и снова.

Самое простое решение:

 public List<Object> getPropList(){
    if(propList==null){
        propList=loadListFromDb();
    }
    return propList;
}

Больше подробностей:

Количество запросов зависит от FetchMode, по умолчанию это FetchMode.SELECT, поэтому он запустит операторы выбора, изменит его на FetchMode.SUBSELECT или FetchMode.JOIN и проверит запросы.

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
@Fetch(FetchMode.SUBSELECT)
private Set<Lesson> teacherLessons;
Другие вопросы по тегам