Grails应用程序维护有关已保存文档的数据。
为具有名为Document
的基本域类的域类创建了简单的域类层次结构。
目前使用table-per-subclass方法。它不是最有效的,但现在还可以。
使用ACL控制对文档的访问,ACL使用另一个域类建模。
在一种特殊情况下,无论实例类型如何(在顶层),都必须将分配给一个ACL的一堆文档分配给另一个ACL。
ACL急需提取文件,并声明批次以优化阅读文档。
class Document {
}
class Image extends Document {
}
class ACL {
Collection documents
static mapping = {
documents lazy: false, batchSize: 100
}
}
启用急切提取并未大幅提升效果。
启用了SQL日志记录来分析问题。我发现Document的记录是按预期获取的,但是对于每个文档,当使用for循环进行迭代时,对文档集合中的每个元素执行附加的子类表连接查询。
ACL original = ACL.get(id)
for (doc in original.documents) {
// Do whatever needs to be done
}
我认为触发了这种行为,因为doc
没有使用显式类型。我试过这个:
ACL original = ACL.get(id)
for (Document doc : original.documents) {
// Do whatever needs to be done
}
不幸的是它没有帮助。
有没有办法告诉Grails它不会从子类的表中获取数据,因为它没有必要:只使用基类?
答案 0 :(得分:1)
不,没有办法告诉Hibernate(实际上这是做这个,而不是Grails)来做到这一点。如果需要这种类型的优化,则需要使用原始SQL,而不是HQL或基于GORM的查询。
要解释为什么这是不可能的,您需要从ORM角度考虑这一点。在您的域示例中,您已在此处展示了" Documents"没有被保存,"图像"是。具体实例总是" Image"永远不会"文件"。为了水化文档列表,ORM不仅必须加载来自基类的数据,还要加载实现类。这是不可避免的。避免这种情况会创建一个类的实例,该类不是域的有效表示。
这是您使用ORM必须支付的价格之一。