我知道这个问题已多次发布,但我想问一下细节,
使用Oracle,你不能传递超过1000个参数的IN子句,所以使用hracle的oracle可能会有一些解决这个问题的方法,如:
1-在每个1000参数列表的IN子句之间使用OR子句,但这不适用,因为oracle的其他限制因为整个查询参数不超过2000
2-使用for循环,每次以1000个参数列表运行查询,然后追加所有结果,如果你需要排序,或者使用不同级别修改的标准api,这不是很好
3-将参数列表放在临时物理表中,并加入它,甚至在子标准中使用它,这个解决方案我不能尝试,因为我不知道如何创建临时表使用休眠,然后使用它,
所以,如果使用CRITERIA api有任何其他想法,请分享,或者即使有一个简单的方法来处理解决方案编号'3'
问候,
答案 0 :(得分:5)
首先,您需要将超过2000个ID(通过您的第一点判断)传递给查询这一事实本身就是一个警告铃。也许有更好的方法来解决潜在的问题。
您可以使用方法#2并对每个列表进行排序,然后在应用程序中执行mergesort。这将需要额外的代码,但可能(假设实际查询相对较快)比方法#3执行得更好。
对于#3,处理临时表有两大缺点:
Table.sqlTemporaryTableCreateString
方法,它在Dialect
类中使用了一堆支持方法),它们在内部使用,需要额外编码才能使用可从应用程序访问。sqlRestriction
。答案 1 :(得分: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);
答案 2 :(得分:0)
如果要使用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;
希望它能对您有所帮助。