';列表中表达式的最大数量为1000';Grails和Oracle的错误
我正在将Grails与Oracle数据库一起使用。我的应用程序中的大多数数据都是如下层次结构的一部分(每个项目包含以下内容):';列表中表达式的最大数量为1000';Grails和Oracle的错误,oracle,grails,gorm,Oracle,Grails,Gorm,我正在将Grails与Oracle数据库一起使用。我的应用程序中的大多数数据都是如下层次结构的一部分(每个项目包含以下内容): 方向 团体 建筑工地 合同 检查 不合规 对用户可见的数据根据其访问进行过滤,根据用户角色,访问可以是方向、组或建筑场地级别 通过为BuildingSite域类创建一个listWithSecurity方法,我们可以很容易地实现这一点,而不是在系统的大部分部分使用list。我们为合同创建了另一个listWithSecurity方法。它基本上是一个Contract.fi
- 方向
- 团体
- 建筑工地
- 合同
- 检查
- 不合规
是否有人以更优雅、更高效的方式遇到并解决了这个问题?与Juergen的评论相同,我通过创建一个DB视图来处理类似的问题,该视图将用户/角色访问规则在其最精细的级别(在您的情况下构建站点?)进行了最低程度的扁平化,此视图可能只包含两列:建筑场地ID和用户/组名称。因此,在用户具有方向级访问权限的情况下,他/她在安全视图中会有许多行—一行用于允许用户访问的方向的每个子建筑场地 然后,创建一个只读GORM类映射到您的安全视图,将其连接到其他域类,并使用视图的用户/角色字段进行过滤。如果运气好的话,您完全可以在GORM中完成这项工作(这里有一些提示:)
不过,您可能需要从Hibernate中获得一些乐趣:这不会赢得任何效率奖励,但我认为如果您只是简单地需要查询1000多个项目的列表,那么我会将其作为一个选项发布,没有一个更有效的选项可用/合适。(这个stackoverflow问题位于谷歌搜索“grails oracle 1000”结果的顶部) 在grails标准中,您可以使用Groovy的collate()方法来分解列表 与此相反:
def result = MyDomain.createCriteria().list {
'in'('id', idList)
}
…将引发此异常:
could not execute query
org.hibernate.exception.SQLGrammarException: could not execute query
at grails.orm.HibernateCriteriaBuilder.invokeMethod(HibernateCriteriaBuilder.java:1616)
at TempIntegrationSpec.oracle 1000 expression max in a list(TempIntegrationSpec.groovy:21)
Caused by: java.sql.SQLSyntaxErrorException: ORA-01795: maximum number of expressions in a list is 1000
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440)
你会得到这样的结果:
def result = MyDomain.createCriteria().list {
or { idList.collate(1000).each { 'in'('id', it) } }
}
不幸的是,当您尝试使用Oracle方言创建一个超过1000项的inList时,Hibernate或Grails并没有在幕后为您做到这一点
我同意关于重构设计以不产生1000多个项目列表这一主题的许多讨论,但无论如何,上面的代码将完成这项工作。编写自己的查询/sql并将它们放入存储过程或视图中可能是一种选择。如果您知道或者有一个期望,那么grails应该在您的案例中生成什么样的查询,然后尝试一下。看起来,这些查询将是应用程序/系统中非常重要的一部分。
def result = MyDomain.createCriteria().list {
or { idList.collate(1000).each { 'in'('id', it) } }
}