HQL查询需要很长时间才能执行

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 
} 
+0

亲爱的,发布您的VersionData POJO定义。 –

+0

已添加版本数据 – Evgen

+0

对于每个VersionData,您都有一个TermData的列表,因此您必须在此添加TermData的定义。这是主要查询深度的导入。 –

好了,有了标准查询你贴,你只取你需要的领域,同时又与你的HQL查询您获取整个Hibernate的管理实体(VersionData)。根据这个实体的配置方式,你可能会看到其他查询被触发来填充这个实体的字段。

您可能会对HQL做与标准相同的事情,在我看来,它比使用标准更容易理解,因此可以维护。仅仅定义你想取,用适当的构造领域的Java类MyClass的,并调用一个HQL查询它看起来像:

"select new path.to.myclass.MyClass (" 
       + " alias1.field1, " 
       + " alias2.field2, " 
       + " ... " 

其中别名是你给的实体的名称在您的HQL查询(例如,version是您编写的查询中的VersionData的别名)。没有预测,没有额外的抽象,只是一个类似SQL的查询。

而不是定义一个新的类来保存字段从HQL查询返回的(我觉得这更方便),您可以直接获取字段,然后处理结果返回,如下面的链接:

How to retrieve only certain fields of an entity in JPQL or HQL? What is the equivalent of ResultSet in JPQL or HQL?

+0

这是通常的做法,为您想要获取的字段创建一个新类。如果我有很多不同的查询,我不需要获取所有的VersionData模型,那么与使用createCriteria或使用createQuery和长期选择\t必需字段进行比较,制作大量类和HQL是非常有益的。我对维护HQL或createCriteria没有任何经验,所以我不知道什么会更好。 – Evgen

+0

@Evgen您可以从'VersionData'扩展'MyClass'并使用结果转换器填充它。对于嵌套投影,你可以添加一些setters。或者您可以直接将嵌套投影映射到'VersionData'。它需要一个特殊的定制变压器。像[FluentHibernateResultTransformer](https:// github。COM/V-ladynev /流利-休眠/斑点/主/流利-休眠核/ SRC /主/ JAVA/COM/github上/流利/休眠/内部/变压器/ FluentHibernateResultTransformer.java)。 –

+0

如果您不希望创建大量课程,请按照所示链接进行操作。另一方面,这些字段可以对应于,例如,列表中的行向最终用户呈现,并且在这种情况下,我认为将它们放在课堂中是有利的。至于通常的做法,我认为Hibernate鼓励开发人员使用他们的标准抽象而不是使用HQL查询,因为前者更“面向对象”。然而,根据我的个人经验,使用标准的代码难以维护,并且比HQL/JPQL查询检查正确性。 –