2013-04-11 68 views
0

我有一个包含144个记录(行)的任务表。我使用普通的select查询来获取所有记录,但JProfiler报告的方法所花费的时间对于这么少量的数据来说太多了。休眠QueryImpl.list优化

Here是JProfiler的快照。

我担心的是org.hibernate.impl.QueryImpl.list所花费的时间。当我在数据库工具中运行正常的sql查询时,它需要0.016秒来获取所有记录,但这里需要更多时间。

我该如何缩短这个时间,达到什么程度?这真的可以减少吗?或约3秒是好吗?

使用的数据库是MySql。

下面是一个获取日期

public List<Backlog> findBacklogList() { 
    Query query = (Query) getSession().createQuery("from Backlog"); 
    List<Backlog> backlogList = (List<Backlog>) query.list(); 
    return backlogList; 
} 

下面的方法是积压POJO的

public class Backlog implements Serializable { 

/** 
* 
*/ 
private static final long serialVersionUID = 1L; 
private Long taskId; 
private String taskName; 
private TaskType taskType; 
private Member createdBy; // String 
private Date createdDate; 
private Member updatedBy; // String 
private Date updatedOn; 
private Status status; 
private Priority priority; 
private String approved; 
private Member completedBy; 
private Member ownedBy; 
private BacklogGroup group; 
private Set<OtherPeople> otherPeople; 
private String activeStatus; 
private String statusChanged; 
private String description; 
private Date expectedEndDate; 

/** 
* @return the taskId 
*/ 
@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "taskid", nullable = false, unique = true, insertable = false) 
public Long getTaskId() { 
    return taskId; 
} 

/** 
* @param taskId 
*   the taskId to set 
*/ 
public void setTaskId(Long taskId) { 
    this.taskId = taskId; 
} 

/** 
* @return the taskName 
*/ 
@Column(name = "taskname", nullable = false, unique = true) 
public String getTaskName() { 
    return taskName; 
} 

/** 
* @param taskName 
*   the taskName to set 
*/ 
public void setTaskName(String taskName) { 
    this.taskName = taskName; 
} 

/** 
* @return the taskType 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "tasktype", referencedColumnName = "id", nullable = false) 
public TaskType getTaskType() { 
    return taskType; 
} 

/** 
* @param taskType 
*   the taskType to set 
*/ 
public void setTaskType(TaskType taskType) { 
    this.taskType = taskType; 
} 

/** 
* @return the createdDate 
*/ 
@Column(name = "createdDate", nullable = false) 
public Date getCreatedDate() { 
    return createdDate; 
} 

/** 
* @param createdDate 
*   the createdDate to set 
*/ 
public void setCreatedDate(Date createdDate) { 
    this.createdDate = createdDate; 
} 

/** 
* @return the updatedBy 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "updatedBy") 
public Member getUpdatedBy() { 
    return updatedBy; 
} 

/** 
* @param updatedBy 
*   the updatedBy to set 
*/ 
public void setUpdatedBy(Member updatedBy) { 
    this.updatedBy = updatedBy; 
} 

/** 
* @return the updatedOn 
*/ 
@Column(name = "updatedOn") 
public Date getUpdatedOn() { 
    return updatedOn; 
} 

/** 
* @param updatedOn 
*   the updatedOn to set 
*/ 
public void setUpdatedOn(Date updatedOn) { 
    this.updatedOn = updatedOn; 
} 

/** 
* @return the status 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "status", referencedColumnName = "id", nullable = false) 
public Status getStatus() { 
    return status; 
} 

/** 
* @param status 
*   the status to set 
*/ 
public void setStatus(Status status) { 
    this.status = status; 
} 

/** 
* @return the priority 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "priority", referencedColumnName = "id", nullable = false) 
public Priority getPriority() { 
    return priority; 
} 

/** 
* @param priority 
*   the priority to set 
*/ 
public void setPriority(Priority priority) { 
    this.priority = priority; 
} 

/** 
* @return the approved 
*/ 
@Column(name = "approved") 
public String getApproved() { 
    return approved; 
} 

/** 
* @param approved 
*   the approved to set 
*/ 
public void setApproved(String approved) { 
    this.approved = approved; 
} 

/** 
* @return the completedBy 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "completedBy") 
public Member getCompletedBy() { 
    return completedBy; 
} 

/** 
* @param completedBy 
*   the completedBy to set 
*/ 
public void setCompletedBy(Member completedBy) { 
    this.completedBy = completedBy; 
} 

/** 
* @return the otherPeople 
*/ 
@OneToMany(mappedBy = "task", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
public Set<OtherPeople> getOtherPeople() { 
    return otherPeople; 
} 

/** 
* @param otherPeople 
*   the otherPeople to set 
*/ 
public void setOtherPeople(Set<OtherPeople> otherPeople) { 
    this.otherPeople = otherPeople; 
} 

/** 
* @return the group 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "groupid", referencedColumnName = "id", nullable = false) 
public BacklogGroup getGroup() { 
    return group; 
} 

/** 
* @param group 
*   the group to set 
*/ 
public void setGroup(BacklogGroup group) { 
    this.group = group; 
} 

/** 
* @return the createdBy 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "createdBy", nullable = false) 
public Member getCreatedBy() { 
    return createdBy; 
} 

/** 
* @param createdBy 
*   the createdBy to set 
*/ 
public void setCreatedBy(Member createdBy) { 
    this.createdBy = createdBy; 
} 

/** 
* @return the activeStatus 
*/ 
@Column(name = "activeStatus") 
public String getActiveStatus() { 
    return activeStatus; 
} 

/** 
* @param activeStatus 
*   the activeStatus to set 
*/ 
public void setActiveStatus(String activeStatus) { 
    this.activeStatus = activeStatus; 
} 

/** 
* @return the statusChanged 
*/ 
@Column(name = "statusChanged") 
public String getStatusChanged() { 
    return statusChanged; 
} 

@Column(name = "expectedEndDate") 
public Date getExpectedEndDate() { 
    return expectedEndDate; 
} 

public void setExpectedEndDate(Date expectedEndDate) { 
    this.expectedEndDate = expectedEndDate; 
} 

/** 
* @param statusChanged 
*   the statusChanged to set 
*/ 
public void setStatusChanged(String statusChanged) { 
    this.statusChanged = statusChanged; 
} 

/** 
* @return the description 
*/ 
@Column(name = "description", length = 5000) 
public String getDescription() { 
    return description; 
} 

/** 
* @param description 
*   the description to set 
*/ 
public void setDescription(String description) { 
    this.description = description; 
} 

/** 
* @return the ownedBy 
*/ 
@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "ownedBy", nullable = false) 
public Member getOwnedBy() { 
    return ownedBy; 
} 

/** 
* @param ownedBy the ownedBy to set 
*/ 
public void setOwnedBy(Member ownedBy) { 
    this.ownedBy = ownedBy; 
} 

/* 
* (non-Javadoc) 
* @see java.lang.Object#hashCode() 
*/ 
@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + ((taskId == null) ? 0 : taskId.hashCode()); 
    return result; 
} 

/* 
* (non-Javadoc) 
* @see java.lang.Object#equals(java.lang.Object) 
*/ 
@Override 
public boolean equals(Object obj) { 
    if (this == obj) { 
     return true; 
    } 
    if (obj == null) { 
     return false; 
    } 
    if (!(obj instanceof Backlog)) { 
     return false; 
    } 
    Backlog other = (Backlog) obj; 
    if (taskId == null) { 
     if (other.taskId != null) { 
      return false; 
     } 
    } else if (!taskId.equals(other.taskId)) { 
     return false; 
    } 
    return true; 
} 

}

+0

发布需要0.016秒才能获取所有数据的正常查询。 – 2013-04-11 05:57:20

+0

select * from backlog – 2013-04-11 05:58:59

+1

正如koljaTM所说,您的Backlog类有各种相关的pojos,这些pojos被设置为热切地获取。所以当你获取这个查询来获取这个关联的数据也会被执行。将相关属性延迟加载的良好做法会减少获取Backlog数据所需的时间。 – 2013-04-11 06:02:03

回答

0

我的猜测是,该查询获得所有相关的数据,以及,例如其他人集,可能很大。尝试激活hibernate sql日志以查看哪些语句实际执行。如果您为每个结果行(或甚至多个)获取单独的子查询,则可能有问题。考虑不要急于获取或将某些关系设置为FetchJoin,以便数据立即连接,如果您知道您将需要它。 如果您不需要数据,请不要选择它。如果您对大量结果感兴趣,但仅对其中的较小数据子集(例如,对于概览列表)有时,建立一个仅用于查询的额外对象也是一个好主意。

+0

感谢koljaTM,懒惰的抓取做到了把戏,并将时间缩短到了1205ms,但是再一次,** org.hibernate.PersistentSet.isEmpty **正在被调用,另外需要1705ms的时间加上该方法的总时间为3秒。在这种情况下还能做些什么? – 2013-04-11 06:39:42

+0

[jprofiler快照](https://lh3.googleusercontent.com/-E0KW_zFELGo/UWZW7yH2edI/AAAAAAAAAoE/5UW83-unOS4/s555/jprofiler2.png) – 2013-04-11 06:40:38

0

为了减少在使用Hibernate时获取数据所需的时间,首先要尽可能使用Lazy加载。

@ManyToOne(fetch = FetchType.EAGER)// This will take more time 

在您的pojo改变EAGER加载到LAZY如果可能的话。

@ManyToOne(fetch = FetchType.LAZY) 

另一件事是使印刷Hibernate执行查询,那里你可以看到很多实际的查询是如何得到执行,以获取单个对象。

您可以通过在休眠配置中将hibernate.show_sql属性设置为true来完成此操作。

<property name="show_sql">true</property> 

您可以在here了解更多关于休眠优化的信息。

+0

您好code13,我已经做到了这一点,减少了时间,但作为你可以请参阅上面的注释,PersistentSet类有一个新的问题。请参阅[快照](https://lh3.googleusercontent.com/-E0KW_zFELGo/UWZW7yH2edI/AAAAAAAAAoE/5UW83-unOS4/s555/jprofiler2.png) – 2013-04-11 07:07:15