HQL查询需要很长时间才能执行
我知道要休眠。 我有一个SQL语句HQL查询需要很长时间才能执行
SELECT VERSION_ID,D_BEGIN,D_END,
(SELECT NAME FROM zvit where ZVIT_ID=version.ZVIT_ID) as name
FROM version
where VERSION_ID in
(SELECT term.VERSION_ID FROM term
where term.PERIOD_MONTH= :periodMonth and term.PERIOD_TYPE= :periodType and term.PERIOD_YEAR= :periodYear)
order by 1 ;
我试着用个createCriteria和HQL来实现它。
DetachedCriteria subQuery = DetachedCriteria.forClass(TermData.class)
.add(Restrictions.eq("periodmonth", periodMonth))
.add(Restrictions.eq("periodtype", periodType))
.add(Restrictions.eq("periodyear", periodYear))
.setProjection(Projections.projectionList()
.add(Projections.property("versionId.versionId"))
);
Criteria versionCriteria = session.createCriteria(VersionData.class)
.addOrder(Order.asc("versionId"))
.add(Subqueries.propertyIn("versionId", subQuery))
.createAlias("zvitId", "zvitId", org.hibernate.sql.JoinType.INNER_JOIN)
.setProjection(Projections.projectionList()
.add(Projections.property("versionId"))
.add(Projections.property("dbegin"))
.add(Projections.property("dend"))
.add(Projections.property("zvitId.name"), "name")
);
HQL:
Query query = session.createQuery(""
+ "from VersionData as version "
// + "inner join version.zvitId as zvit "
+ "where version.versionId in "
+ "(select term.versionId from TermData as term "
+ "where term.periodmonth= :periodmonth and term.periodtype= :periodtype and term.periodyear= :periodyear)");
的问题是,这个HQL需要10倍更长的时间来执行。并做了很多不必要的查询。我试图与评论对象来做这件事,它改善了一点,但仍然工程5的时间比个createCriteria查询时间更长,除了我得到VersionData和ZvitData对象我不能这样做皈依
List<VersionData> queryResult = query.list();
。这似乎不是一个问题,但我仍然不明白为什么我没有收到只是VersionData对象。 但是还有一个更重要的问题是有没有什么办法可以改善这个HQL语句,以便与mysql或createCriteria查询同时执行。
VersionData defenition
@Entity
@Table(name = "version")
public class VersionData implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 7355281418627668744L;
@Id
@Column(name="VERSION_ID")
private String versionId;
/**
* user dbegin
*/
@Column(name = "D_BEGIN")
@Type(type = "date")
private Date dbegin;
/** user dend */
@Column(name = "D_END")
@Type(type = "date")
private Date dend;
/**
* user zvitId
*/
@ManyToOne
@JoinColumn(name="ZVIT_ID")
private ZvitData zvitId;
@OneToMany(targetEntity=TermData.class, mappedBy = "versionId", cascade=javax.persistence.CascadeType.ALL, fetch=FetchType.LAZY)
private List<TermData> terms;
//getters, setters, hashcode, equals
}
好了,有了标准查询你贴,你只取你需要的领域,同时又与你的HQL查询您获取整个Hibernate的管理实体(VersionData)。根据这个实体的配置方式,你可能会看到其他查询被触发来填充这个实体的字段。
您可能会对HQL做与标准相同的事情,在我看来,它比使用标准更容易理解,因此可以维护。仅仅定义你想取,用适当的构造领域的Java类MyClass的,并调用一个HQL查询它看起来像:
"select new path.to.myclass.MyClass ("
+ " alias1.field1, "
+ " alias2.field2, "
+ " ... "
其中别名是你给的实体的名称在您的HQL查询(例如,version是您编写的查询中的VersionData的别名)。没有预测,没有额外的抽象,只是一个类似SQL的查询。
而不是定义一个新的类来保存字段从HQL查询返回的(我觉得这更方便),您可以直接获取字段,然后处理结果返回,如下面的链接:
这是通常的做法,为您想要获取的字段创建一个新类。如果我有很多不同的查询,我不需要获取所有的VersionData模型,那么与使用createCriteria或使用createQuery和长期选择\t必需字段进行比较,制作大量类和HQL是非常有益的。我对维护HQL或createCriteria没有任何经验,所以我不知道什么会更好。 – Evgen
@Evgen您可以从'VersionData'扩展'MyClass'并使用结果转换器填充它。对于嵌套投影,你可以添加一些setters。或者您可以直接将嵌套投影映射到'VersionData'。它需要一个特殊的定制变压器。像[FluentHibernateResultTransformer](https:// github。COM/V-ladynev /流利-休眠/斑点/主/流利-休眠核/ SRC /主/ JAVA/COM/github上/流利/休眠/内部/变压器/ FluentHibernateResultTransformer.java)。 –
如果您不希望创建大量课程,请按照所示链接进行操作。另一方面,这些字段可以对应于,例如,列表中的行向最终用户呈现,并且在这种情况下,我认为将它们放在课堂中是有利的。至于通常的做法,我认为Hibernate鼓励开发人员使用他们的标准抽象而不是使用HQL查询,因为前者更“面向对象”。然而,根据我的个人经验,使用标准的代码难以维护,并且比HQL/JPQL查询检查正确性。 –
亲爱的,发布您的VersionData POJO定义。 –
已添加版本数据 – Evgen
对于每个VersionData,您都有一个TermData的列表,因此您必须在此添加TermData的定义。这是主要查询深度的导入。 –