Search code examples
springhibernatenhibernate-mappinghibernate-criteria

Hibernate occurs too many queries


I use hibernate(with ehcache)/spring/mysql/jsf.I'am getting data from two tables in mysql.And these tables are as follows:
User
id int (primary key)
name etc.
Lesson
id int (primary key)
lesson varchar
teacher_id int (foreign key from user(id) )

and Lesson model class:

@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

User model Class

@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

I'm getting lesson list with this daoimpl.

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;
}

This query is getting lessons of the current user.My jsf page below:

<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>

When I opened this page,I get the following output in console.

Hibernate: select lesson0_.id as id0_, lesson0_.lesson as lesson0_, lesson0_.teacher_id as teacher3_0_ from oys_lesson lesson0_ where lesson0_.teacher_id in (select user1_.id from oys_user user1_ left outer join oys_user_role user1_1_ on user1_.id=user1_1_.user_id where user1_.username=?)

When page opened,This query is running 3 times.3 of the same query.But when I selected row.dialog window opens and running the same query more 19 times.

managedBean.class

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

Why is running the same query repeatedly?When the dialog window opens, do not need to run any query?Why it works 19 times?thanks in advance..


Solution

  • I solved my problem.Hibernate occurs too many queries.Because JSF calls getters multiple times.So my getList methods works multiple times.

    This usually is not seen as a major problem.Because getter method is a very cheap operation.

    But, if you're performing expensive business logic(db operation) in the getter method (like me),this would be re-executed everytime.So, the same query(in the getter method) works again and again.

    The simplest solution:

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

    For more details: