Hibernate 发生太多查询
Hibernate occurs too many queries
我使用休眠(带 ehcache)/spring/mysql/jsf。我从 mysql.And 中的两个表中获取数据,这些表如下:
用户
id int (主键)
姓名等
课程
id int (主键)
课程 varchar
teacher_id int(来自用户(id)的外键)
和课程模型类s:
@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
用户模型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
我正在获取这个 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;
}
此查询正在获取以下当前 user.My 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: 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=?)
当页面打开时,这个查询是 运行ning 3 次。3 of the same query
。但是当我选择 row.dialog window 打开并 运行ning相同的查询更多 19 times
.
managedBean.class
@ManagedBean
@SessionScoped
public class LessonManagedBean implements Serializable {
private Lesson selectedLesson=null;
List<Lesson> lessonList;
//Getters and Setters
为什么 运行 重复同一个查询?当对话框 window 打开时,不需要 运行 任何查询?为什么它有效 19 次?提前致谢。 .
查询数量取决于FetchMode, by default it is FetchMode.SELECT, so it will fire select statements, change it to FetchMode.SUBSELECT or FetchMode.JOIN并检查查询。
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
@Fetch(FetchMode.SUBSELECT)
private Set<Lesson> teacherLessons;
我解决了我的 problem.Hibernate 发生太多 queries.Because JSF 调用 getter 多次 times.So 我的 getList 方法多次工作。
这通常不被视为主要 problem.Because getter 方法是一种非常便宜的操作。
但是,如果你在 getter 方法中执行昂贵的业务逻辑(数据库操作)(像我一样),这将被重新执行 everytime.So,相同的查询(在 getter方法)一次又一次地工作。
最简单的方案:
public List<Object> getPropList(){
if(propList==null){
propList=loadListFromDb();
}
return propList;
}
更多详情:
- Why JSF calls getters multiple times?
我使用休眠(带 ehcache)/spring/mysql/jsf。我从 mysql.And 中的两个表中获取数据,这些表如下:
用户
id int (主键)
姓名等
课程
id int (主键)
课程 varchar
teacher_id int(来自用户(id)的外键)
和课程模型类s:
@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
用户模型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
我正在获取这个 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;
}
此查询正在获取以下当前 user.My 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: 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=?)
当页面打开时,这个查询是 运行ning 3 次。3 of the same query
。但是当我选择 row.dialog window 打开并 运行ning相同的查询更多 19 times
.
managedBean.class
@ManagedBean
@SessionScoped
public class LessonManagedBean implements Serializable {
private Lesson selectedLesson=null;
List<Lesson> lessonList;
//Getters and Setters
为什么 运行 重复同一个查询?当对话框 window 打开时,不需要 运行 任何查询?为什么它有效 19 次?提前致谢。 .
查询数量取决于FetchMode, by default it is FetchMode.SELECT, so it will fire select statements, change it to FetchMode.SUBSELECT or FetchMode.JOIN并检查查询。
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
@Fetch(FetchMode.SUBSELECT)
private Set<Lesson> teacherLessons;
我解决了我的 problem.Hibernate 发生太多 queries.Because JSF 调用 getter 多次 times.So 我的 getList 方法多次工作。
这通常不被视为主要 problem.Because getter 方法是一种非常便宜的操作。
但是,如果你在 getter 方法中执行昂贵的业务逻辑(数据库操作)(像我一样),这将被重新执行 everytime.So,相同的查询(在 getter方法)一次又一次地工作。
最简单的方案:
public List<Object> getPropList(){
if(propList==null){
propList=loadListFromDb();
}
return propList;
}
更多详情:
- Why JSF calls getters multiple times?