[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-1123) Cannot put more than 1000 elements in a InExpression
FCT (JIRA)
noreply at atlassian.com
Thu Feb 5 10:29:40 EST 2009
[ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1123?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=32325#action_32325 ]
FCT commented on HHH-1123:
--------------------------
My workaround basically substitue named-parameterS of clause in by: in(1000-elements) or in(1000-elements) or... if necessary, only if collection.size()>1000.
If collection.size()>1000 I use regular expression to manipulate original query and get a new query.
Named-parameters of in clause are replaced by new ins clauses that support 1000 elements each in.
Example 1 (in):
entity.identifier in (1,2,3,...,1001) is replaced by entity.identifier in (1,2,3,...,1000) or in (1001)
Example 1 (not in):
entity.identifier not in (1,2,3,...,1001) is replaced by not(entity.identifier in (1,2,3,...,1000) or in (1001))
I documented code with implications of each statement.
private static Query translateIn(final Collection<?> values,
final Query query, final String param) {
// collection size. *Can do a hit in database
final int size = values.size();
// mod to know how much elements are inputted in last clause IN
final int mod = (size % 1000);
// calculate how much INs are injected
final int numberOfIn = (size / 1000) + (mod == 0 ? 0 : 1);
// cache of new named-parameters
final List<String> params = new ArrayList<String>();
/*
* Regular expression find pattern of in 'clause. obj.property.id in (itens)' or 'clause. obj.property.id no in (itens)'
*/
final String regex = "([\\w\\.]+)\\s+(not\\s+)?in\\s*\\(\\s*:" + param
+ "\\s*\\)";
final StringBuilder in = new StringBuilder(" $2 (");
// manipulation string. it will can be expensive.
for (int i = 0; i < numberOfIn; i++) {
// Cria um novo named-parameter.
final StringBuilder newNameParam = new StringBuilder();
newNameParam.append(param);
newNameParam.append(NAMED_PARAMETER);
newNameParam.append(i);
/*
* generate string of replacement by group defined to pattern: $1 is property use in clause
*/
in.append("$1 in (:");
in.append(newNameParam.toString());
in.append(")");
// hold params
params.add(newNameParam.toString());
if (i + 1 < numberOfIn) {
// If there is more in clause to append then include or.
in.append(" or ");
}
}
in.append(") ");// clouse all 'in'
// do replace of old in by new genereted ins. *Cost beacuse has compile a regular expression always.
final String newQueryString = query.getQueryString().replaceAll(regex,
in.toString());
// Create new query. *Cost to create a new query
final Query newQuery = getSession().createQuery(newQueryString);
// Get list. *Cost create item by item
final List<Object> copy = new ArrayList<Object>(values);
for (int count = 0, from = 0, to = 1000; count < numberOfIn; count++) {
// Currently named-parameter
final String nameParam = params.get(count);
// get sublist and link named-parameter with it.
newQuery.setParameterList(nameParam, copy.subList(from, to));
/*
* to next step for update 'from' with 'to'
*/
from = to;
if (count + 2 < numberOfIn) {
//execute this statament except in last iteration
to += 1000;
}
else if (count + 2 == numberOfIn) {
//In this statement can set 1000 elements or mod calculated value itens list
to += (mod == 0) ? 1000 : mod;
}
}
return newQuery;
}
> Cannot put more than 1000 elements in a InExpression
> ----------------------------------------------------
>
> Key: HHH-1123
> URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1123
> Project: Hibernate Core
> Issue Type: Bug
> Components: core
> Affects Versions: 3.1 rc2, 3.2.0.alpha1
> Environment: Oracle 9i
> Reporter: Alexis Seigneurin
> Attachments: patch.txt
>
> Original Estimate: 1 hour
> Remaining Estimate: 1 hour
>
> The number of elements that we can put in a "in" expression is limited to a certain amount (1000 for Oracle, for instance). When creating a criteria query, the org.hibernate.criterion.InExpression class should split the expression into several smaller ones.
> Attached is a patch which splits the expression by slices of 500 elements. For example, if we have 1001 elements to put in the "in" expression, the result would be :
> (entity.field in (?, ?, ?...) or entity.field in (?, ?, ?...) or entity.field in (?))
> The surrounding parantheses are useful to avoid problems with other conditions (a "and" condition taking over the one of the "or" conditions).
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the hibernate-issues
mailing list