你好,我有一个大型的Oracle Hibernate Web应用程序,似乎出现了以下错误:
ORA-01795: 列表中的表达式数量已达到最大值1000
我需要一个Java代码,并且由一个Hibernate的用户定义组件进行测试,以便将其尽可能简单地添加到我的屏幕搜索Java类中。请问是否有人有这样经过测试的组件?
你好,我有一个大型的Oracle Hibernate Web应用程序,似乎出现了以下错误:
ORA-01795: 列表中的表达式数量已达到最大值1000
我需要一个Java代码,并且由一个Hibernate的用户定义组件进行测试,以便将其尽可能简单地添加到我的屏幕搜索Java类中。请问是否有人有这样经过测试的组件?
我尝试了下面这段代码,来自链接,它似乎非常有效,以防将来链接失效,我将复制代码。
保持简单,保持微笑:)
/**
* An utility method to build the Criterion Query IN clause if the number of parameter
* values passed has a size more than 1000. Oracle does not allow more than
* 1000 parameter values in a IN clause. Doing so a {@link SQLException} is
* thrown with error code, 'ORA-01795: maximum number of expressions in a list is 1000'.
* @param propertyName
* @param values
* @return
*/
import java.util.List;
import org.hibernate.criterion.Restrictions;
/**
*
* @author 2796
*/
public class SplitHibernateIn {
private static int PARAMETER_LIMIT = 999;
public static org.hibernate.criterion.Criterion buildInCriterion(String propertyName, List values) {
org.hibernate.criterion.Criterion criterion = null;
int listSize = values.size();
for (int i = 0; i < listSize; i += PARAMETER_LIMIT) {
List subList;
if (listSize > i + PARAMETER_LIMIT) {
subList = values.subList(i, (i + PARAMETER_LIMIT));
} else {
subList = values.subList(i, listSize);
}
if (criterion != null) {
criterion = Restrictions.or(criterion, Restrictions.in(propertyName, subList));
} else {
criterion = Restrictions.in(propertyName, subList);
}
}
return criterion;
}
}
private static int PARAMETER_LIMIT = 999;
private static Predicate createInStatement(CriteriaBuilder cb, Path fieldName, List values) {
int listSize = values.size();
Predicate predicate = null;
for (int i = 0; i < listSize; i += PARAMETER_LIMIT) {
List subList;
if (listSize > i + PARAMETER_LIMIT) {
subList = values.subList(i, (i + PARAMETER_LIMIT));
} else {
subList = values.subList(i, listSize);
}
if (predicate == null) {
predicate = fieldName.in(subList);
} else {
predicate = cb.or(predicate, fieldName.in(subList));
}
}
return predicate;
}
public List<Bean> getBeanList(List<Long> pkList) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Bean> query = cb.createQuery(Bean.class);
Root<Bean> root = query.from(Bean.class);
// "Bean_" is a @StaticMetamodel(Bean.class)
Predicate inStatement = createInStatement(cb, root.get(Bean_.pk), pkList);
query.select(root).where(inStatement);
return entityManager.createQuery(query).getResultList();
}
虽然目前的答案都不错,但我认为这个答案更简单易懂,实现起来也更容易:
private <T> Disjunction restrictionPropertyIn(String property, ArrayList<T> list) {
Disjunction criterion = Restrictions.disjunction();
for (List<T> idSubset : Lists.partition(list, 1000)) {
criterion.add(Restrictions.in(property, idSubset));
}
return criterion;
}
Restrictions.disjunction()
相当于使用 Restrictions.or()
连接多个 Criteria
。Lists
是 Guava 中的实用工具类;partition(list, limit)
将 list
拆分成大小为 limit
的子列表。返回的 Criterion
可以直接在任何期望 Criterion
的地方使用,例如:
List<Long> fiveThousandIds = Arrays.asList(1, 2, 3, ..., 999, 1000, 1001, ..., 5000);
Criteria crit = session.createCriteria(Employee.class);
crit.add(restrictionPropertyIn("employeeId", fiveThousandIds));
crit.list();
IN
子句限制,您可以将硬编码的1000
更改为参数。X IN(...)OR X IN(...)
的常见用法。此外,对于这个问题的每个答案都使用了 OR
;我的解决方法只需要4行而不是20行。这是我们几年来一直在使用的方式。 - walen