【发布时间】:2012-02-17 17:06:40
【问题描述】:
我将 Grails 与 Oracle 数据库一起使用。我的应用程序中的大部分数据都是这样的层次结构的一部分(每个项目都包含以下项目):
- 方向
- 组
- 建筑工地
- 合同
- 检查
- 不合格
用户可见的数据会根据其访问权限进行过滤,根据用户角色的不同,访问权限可以是方向、组或建筑工地级别。
我们通过为 BuildingSite 域类创建一个 listWithSecurity 方法轻松地实现了这一点,我们在大多数系统中都使用该方法而不是 list。我们为 Contract 创建了另一个 listWithSecurity 方法。它基本上做了一个 Contract.findAllByContractIn(BuildingSite.listWithSecurity)。以此类推。这样做的好处是将所有实际访问逻辑保留在 BuildingSite.listWithsecurity 中。
当我们开始在系统中获取真实数据时,问题就出现了。我们很快就遇到了“ora-01795 列表中的最大表达式数为 1000”的错误。很公平,传递超过 1000 个文字的列表并不是最有效的方法,因此我尝试了其他方法,即使这意味着我必须将安全逻辑驱逐到每个控制器。
显而易见的方法似乎使用了这样的标准(为了简单起见,我只在这里放置了方向级别的访问权限):
def c = NonConformity.createCriteria()
def listToReturn = c.list(max:params.max, offset: params.offset?.toInteger() ?: 0)
{
inspection {
contract {
buildingSite {
group {
'in'("direction",listOfOneOrTwoDirections)
}
}
}
}
}
我期待 Grails 生成一个带有连接的单个查询,以避免 ora-01795 错误,但它似乎为每个级别调用单独的查询,并将结果作为“in”中的文字传递回 Oracle 以进行查询另一个层次。换句话说,它与我所做的完全一样,所以我得到了同样的错误。
实际上,它可能正在优化一点。它似乎正在解决问题,但只是为了一个级别。在前面的示例中,我不会收到 1001 次检查的错误,但我会收到 1001 次合同或建筑工地的错误。
我还尝试对 findAll 和单个 HQL where 语句执行基本相同的操作,我将单个方向传递给该语句以在一个查询中获取 nonConformities。一样。它解决了第一关,但我在其他关卡中遇到了同样的错误。
我确实设法通过将我的“输入”标准拆分为“或”内的许多“输入”来修补它,因此没有一个单一的文字列表长度超过 1000,但这是非常丑陋的代码。一个 findAllBy[…]In 变成了 10 多行代码。从长远来看,它可能会导致性能问题,因为我们被困在使用大量参数进行查询。
有没有人遇到过这个问题,并以更优雅高效的方式解决了这个问题?
【问题讨论】:
-
它可能是编写您自己的查询/sql 并将它们放入存储过程或可能的视图中的一个选项。如果您知道或有一个期望,在您的情况下应该生成什么样的查询 grails,然后试一试。看来,这些查询将成为您的应用程序/系统中非常重要的一部分。
标签: oracle grails grails-orm