【问题标题】:Hibernate + Oracle IN clause limitation, how to solve it?Hibernate + Oracle IN 子句限制,如何解决?
【发布时间】:2011-12-07 04:13:38
【问题描述】:

我知道这个问题被发了很多次了,但是我想问一下细节,

使用 Oracle,您不能向 IN 子句传递超过 1000 个参数,因此使用带有 oracle 的 hibernate 可能有一些解决此问题的方法,例如:

1- 在每个 1000 参数列表的 IN 子句之间使用 OR 子句,但由于 oracle 对整个查询参数不超过 2000 的其他限制,这不适用

2-使用for循环,每次查询1000个参数列表,然后追加所有结果,如果需要排序,或者使用不同级别修改的criteria api,这不是很好

p>

3-将参数列表放在临时物理表中,然后加入它,甚至在子条件中使用它,这个解决方案我无法尝试,因为我不知道如何使用创建临时表休眠,然后使用它,

所以如果有任何其他使用 CRITERIA api 的想法,请分享它,或者即使有一种简单的方法来处理解决方案编号“3”

问候,

【问题讨论】:

  • 您能否发布一个查询示例,该查询导致 IN 子句中的值超过 1000 个?
  • 您可以考虑任何查询,例如从表中选择 2000 条记录,甚至将 2000 个参数的列表作为输入传递,我认为这不是问题
  • 什么时候需要传递 2000 个参数作为输入?对我来说听起来像是一种代码味道。

标签: java oracle hibernate


【解决方案1】:

如果您想在 Java 中执行此操作,最好的选择是创建主列表的子列表,然后在查询中使用它:

int DBLIMIT = 2000;
int MAXRESULTS = 1999;
int valueResults = 0;
if (list.size() > DBLIMIT) {
    while (valueResults >= 0) {
    List<String> listMAXRESULTSReg= new ArrayList<>();
    if ((list.size() - (listMAXRESULTSReg.size() + MAXRESULTS * (valueResults + 1))) > 0) {
        listMAXRESULTSReg = list.subList(MAXRESULTS * valueResults, MAXRESULTS * (valueResults + 1));
        valueResults++;
    } else if ((list.size() - (listMAXRESULTSReg.size() + MAXRESULTS * (valueResults + 1))) <= 0) {
        listMAXRESULTSReg = list.subList(MAXRESULTS * valueResults, list.size() - 1);
        valueResults = -1;
    }
    String queryStr = "FROM table" + "WHERE field in (:field) ";
    Query query = session.createQuery(queryStr).setParameter("field", listMAXRESULTSReg);
    resultList.addAll(query.getResultList());
}
return resultList;

希望对你有所帮助。

【讨论】:

    【解决方案2】:

    在 Guava Lists 和 Hibernate Disjunction 的帮助下:

        Disjunction disjunction = Restrictions.disjunction();
        for (List<?> chunkList: Lists.partition(largeList, 1000)) {
            disjunction.add(Restrictions.in(propertyName, chunkList));
        }
        criteria.add(disjunction);
    

    【讨论】:

      【解决方案3】:

      首先,您需要向查询传递超过 2000 个 id(根据您的第一点判断)这一事实本身就是一个警钟。也许有更好的方法来解决根本问题。

      您可以使用方法#2 对每个列表进行排序,然后在应用程序中执行合并排序。这将需要额外的代码,但可能(假设实际查询相对较快)比方法 #3 执行得更好。

      对于#3,处理临时表有两个很大的缺点:

      • 虽然 Hibernate 确实支持它们(查看 Table.sqlTemporaryTableCreateString 方法,它在 Dialect 类中使用了一堆支持方法),但它们是在内部使用的,需要您进行额外的编码才能从应用程序访问.
      • 更重要的是,使用临时表将迫使您将查询编写为原生 SQL(因为它不会被映射)。如果您使用 Criteria API,则必须将 sqlRestriction 与子查询一起使用。

      【讨论】:

      • 我认为你是完全正确的,但是你能帮我解决这个问题吗,有没有办法在运行它之前编辑一个标准,因为标准是通过几种增加限制的方法传递的,并且最后,我希望能够在运行之前检查这些限制
      • @Amr - 不,您将无法编辑 Criteria 实例,至少在不使用反射的肮脏技巧的情况下不能。 Criteria API 几乎是只写的。
      猜你喜欢
      • 2016-06-29
      • 1970-01-01
      • 2023-03-31
      • 2015-12-12
      • 2014-12-11
      • 1970-01-01
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多