DATAJPA-492 - Altered implementation of findAll(Iterable<ID>) to work around bug in OpenJPA.

Changed the implementation of SimpleJpaRepository.findAll(Iterable<ID>) as OpenJPA still doesn't correctly bind in-clauses by name. This has been originally reported in [0] and marked fixed for 2.3.0 but even an upgrade to this version (coming in a subsequent commit) requires the workaround.

[0] https://issues.apache.org/jira/browse/OPENJPA-2018
This commit is contained in:
Oliver Gierke
2014-03-07 18:18:52 +01:00
parent dcc8ad7b73
commit 118245ebd4

View File

@@ -25,9 +25,11 @@ import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.Parameter;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
@@ -272,12 +274,10 @@ public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepos
return Collections.emptyList();
}
return getQuery(new Specification<T>() {
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<?> path = root.get(entityInformation.getIdAttribute());
return path.in(cb.parameter(Iterable.class, "ids"));
}
}, (Sort) null).setParameter("ids", ids).getResultList();
ByIdsSpecification specification = new ByIdsSpecification();
TypedQuery<T> query = getQuery(specification, (Sort) null);
return query.setParameter(specification.parameter, ids).getResultList();
}
/*
@@ -524,4 +524,29 @@ public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepos
LockModeType type = lockMetadataProvider == null ? null : lockMetadataProvider.getLockModeType();
return type == null ? query : query.setLockMode(type);
}
/**
* Specification that gives access to the {@link Parameter} instance used to bind the ids for
* {@link SimpleJpaRepository#findAll(Iterable)}. Workaround for OpenJPA not binding collections to in-clauses
* correctly when using by-name binding.
*
* @see https://issues.apache.org/jira/browse/OPENJPA-2018?focusedCommentId=13924055
* @author Oliver Gierke
*/
@SuppressWarnings("rawtypes")
private final class ByIdsSpecification implements Specification<T> {
ParameterExpression<Iterable> parameter;
/*
* (non-Javadoc)
* @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.persistence.criteria.Root, javax.persistence.criteria.CriteriaQuery, javax.persistence.criteria.CriteriaBuilder)
*/
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<?> path = root.get(entityInformation.getIdAttribute());
parameter = cb.parameter(Iterable.class);
return path.in(parameter);
}
}
}