【问题标题】:Hibernate occurs too many queriesHibernate 发生太多查询
【发布时间】:2015-02-17 12:51:45
【问题描述】:

我使用hibernate(带有ehcache)/spring/mysql/jsf。我从mysql中的两个表中获取数据。这些表如下:
用户
id int(主键)
名称等
课程
id int(主键)
课程 varchar
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

我正在使用这个 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;
}

此查询正在获取当前用户的课程。我的 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>

当我打开此页面时,我在控制台中得到以下输出。

休眠: 从 oys_lesson 课程 0_ 中选择课程 0_.id 作为 id0_,课程 0_.课程作为课程 0_,课程 0_.teacher_id 作为教师 3_0_ 其中课程 0_.teacher_id 在(从 oys_user user1_ 中选择 user1_.id 左外连接 oys_user_role user1_1_ on user1_.id=user1_1_.user_id 其中 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 次?提前谢谢..

【问题讨论】:

    标签: spring hibernate nhibernate-mapping hibernate-criteria


    【解决方案1】:

    我解决了我的问题。Hibernate 发生了太多查询。因为 JSF 多次调用 getter。所以我的 getList 方法可以多次工作。

    这通常不会被视为主要问题。因为 getter 方法是一种非常便宜的操作。

    但是,如果您在 getter 方法中执行昂贵的业务逻辑(db 操作)(如我),这将每次都重新执行。因此,相同的查询(在 getter 方法中)一次又一次地工作。

    最简单的解决方案:

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

    更多详情:

    【讨论】:

      【解决方案2】:

      查询数量取决于FetchMode,默认为FetchMode.SELECT,因此它会触发select语句,将其更改为FetchMode.SUBSELECTFetchMode.JOIN并检查查询。

      @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
      @Fetch(FetchMode.SUBSELECT)
      private Set<Lesson> teacherLessons;
      

      【讨论】:

      • 我都试过了,但没有任何改变。当对话框窗口打开(选定的行)时,为什么要处理 19 个相同的查询?您对此有何看法?
      猜你喜欢
      • 2017-10-27
      • 1970-01-01
      • 2013-06-10
      • 2021-10-12
      • 1970-01-01
      • 2021-02-20
      • 2014-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多