【问题标题】:HQL and joins - a faster way?HQL 和连接 - 更快的方法?
【发布时间】:2015-08-14 08:42:38
【问题描述】:

我的这部分模型如下:

IQCEntity has many Documents
DocumentCategory has many Documents

我正在为我的 ORM 使用 Hibernate。

现在,请考虑以下方法:

/**
 * Get all documents in the supplied IQCEntity which are in the
 * specified DocumentCategory.
 * @param entity the {@link IQCEntity} which holds the Documents
 * @param category the {@link DocumentCategory} which the Documents belong to
 * @return Collection<{@link Document}>
 */
@SuppressWarnings("unchecked")
public Collection<Document> getDocuments(IQCEntity entity, DocumentCategory category) { 
    String q = "from Document d where d.documentCategory.documentCategoryId = :c and d.entity.entityId = :e";
    Query query = session.createQuery(q);
    query.setParameter("c", category.getDocumentCategoryId());
    query.setParameter("e", entity.getEntityId());
    List<Document> documents = (List<Document>)query.list();
    Collections.sort(documents);
    return documents;
}

这种方法有效,并且可以返回正确的结果,但是它似乎很慢。

如果我查看数据库中的表结构,Document 表有父 ID(当然有 - 否则它怎么会加入!),documentCategory_documentCategoryIdentity_entityId

我们都知道,在 SQL 中完全不需要任何连接就可以得到正确的结果。在 HQL 中如何做到这一点?

我试过这个:(注意 _ 而不是 .)

String q = "from Document d where d.documentCategory_documentCategoryId = :c and d.entity_entityId = :e";

但找不到该属性。

org.hibernate.QueryException: could not resolve property: documentCategory_documentCategoryId of: com.foo.bar.entities.Document

有没有办法引用连接字段而不是对象引用?

【问题讨论】:

  • 父ID是否有索引?
  • 是的,两者都有索引。
  • 记录 Hibernate 生成的 SQL 并检查查询,运行分析器查看热点是什么。
  • 您是否尝试过使用标识符属性.id 来避免连接? String q = "from Document d where d.documentCategory.id = :c and d.entity.id = :e";
  • 谢谢我们!这很好用。我不知道 .id 是一个特殊属性。我希望它会抱怨找不到该属性,但不,这似乎运作良好并消除了连接。

标签: java performance hibernate join hql


【解决方案1】:

要避免连接,请使用 identifier property .id

String q = "from Document d where d.documentCategory.id = :c and d.entity.id = :e";

但由于您也有引用的对象,您甚至可以编写一个较短的版本,使用 entitycategory 作为参数:

String q = "from Document d where d.documentCategory = :c and d.entity = :e";
Query query = session.createQuery(q);
query.setParameter("c", category);
query.setParameter("e", entity);

在这两个版本中,Hibernate 都能够确定它实际上不需要加入。

【讨论】:

  • 再次感谢您!按照你所说的,事实证明我原来的 HQL 查询实际上并没有执行连接!我现在觉得很傻。 Hibernate HQL 好像比我聪明!
猜你喜欢
  • 1970-01-01
  • 2014-09-26
  • 2019-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多