HHH-11278 - setMaxResult(0) should return an empty List

This commit is contained in:
Andrea Boriero 2016-12-19 19:49:18 +00:00 committed by Steve Ebersole
parent d4d1a6b8d4
commit 318473e59c
5 changed files with 230 additions and 1 deletions

View File

@ -252,6 +252,7 @@ public class CriteriaImpl implements Criteria, Serializable {
public Integer getMaxResults() { public Integer getMaxResults() {
return maxResults; return maxResults;
} }
@Override @Override
public Criteria setMaxResults(int maxResults) { public Criteria setMaxResults(int maxResults) {
this.maxResults = maxResults; this.maxResults = maxResults;

View File

@ -0,0 +1,207 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.internal;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.type.Type;
/**
* @author Andrea Boriero
*/
public class EmptyScrollableResults implements ScrollableResultsImplementor {
public static final ScrollableResultsImplementor INSTANCE = new EmptyScrollableResults();
@Override
public boolean isClosed() {
return true;
}
@Override
public int getNumberOfTypes() {
return 0;
}
@Override
public void close() {
}
@Override
public boolean next() {
return false;
}
@Override
public boolean previous() {
return false;
}
@Override
public boolean scroll(int positions) {
return false;
}
@Override
public boolean last() {
return true;
}
@Override
public boolean first() {
return false;
}
@Override
public void beforeFirst() {
}
@Override
public void afterLast() {
}
@Override
public boolean isFirst() {
return false;
}
@Override
public boolean isLast() {
return false;
}
@Override
public int getRowNumber() {
return 0;
}
@Override
public boolean setRowNumber(int rowNumber) {
return false;
}
@Override
public Object[] get() {
return new Object[0];
}
@Override
public Object get(int i) {
return null;
}
@Override
public Type getType(int i) {
return null;
}
@Override
public Integer getInteger(int col) {
return null;
}
@Override
public Long getLong(int col) {
return null;
}
@Override
public Float getFloat(int col) {
return null;
}
@Override
public Boolean getBoolean(int col) {
return null;
}
@Override
public Double getDouble(int col) {
return null;
}
@Override
public Short getShort(int col) {
return null;
}
@Override
public Byte getByte(int col) {
return null;
}
@Override
public Character getCharacter(int col) {
return null;
}
@Override
public byte[] getBinary(int col) {
return new byte[0];
}
@Override
public String getText(int col) {
return null;
}
@Override
public Blob getBlob(int col) {
return null;
}
@Override
public Clob getClob(int col) {
return null;
}
@Override
public String getString(int col) {
return null;
}
@Override
public BigDecimal getBigDecimal(int col) {
return null;
}
@Override
public BigInteger getBigInteger(int col) {
return null;
}
@Override
public Date getDate(int col) {
return null;
}
@Override
public Locale getLocale(int col) {
return null;
}
@Override
public Calendar getCalendar(int col) {
return null;
}
@Override
public TimeZone getTimeZone(int col) {
return null;
}
}

View File

@ -1846,6 +1846,9 @@ public final class SessionImpl
public List list(Criteria criteria) throws HibernateException { public List list(Criteria criteria) throws HibernateException {
// TODO: Is this guaranteed to always be CriteriaImpl? // TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria; CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
if ( criteriaImpl.getMaxResults() != null && criteriaImpl.getMaxResults() == 0 ) {
return Collections.EMPTY_LIST;
}
final NaturalIdLoadAccess naturalIdLoadAccess = this.tryNaturalIdLoadAccess( criteriaImpl ); final NaturalIdLoadAccess naturalIdLoadAccess = this.tryNaturalIdLoadAccess( criteriaImpl );
if ( naturalIdLoadAccess != null ) { if ( naturalIdLoadAccess != null ) {

View File

@ -744,6 +744,9 @@ public class ProcedureCallImpl<R>
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<R> getResultList() { public List<R> getResultList() {
if ( getMaxResults() == 0 ) {
return Collections.EMPTY_LIST;
}
try { try {
final Output rtn = outputs().getCurrent(); final Output rtn = outputs().getCurrent();
if ( ! ResultSetOutput.class.isInstance( rtn ) ) { if ( ! ResultSetOutput.class.isInstance( rtn ) ) {

View File

@ -55,9 +55,11 @@ import org.hibernate.engine.spi.RowSelection;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
import org.hibernate.hql.internal.QueryExecutionRequestException; import org.hibernate.hql.internal.QueryExecutionRequestException;
import org.hibernate.internal.EmptyScrollableResults;
import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.EntityManagerMessageLogger;
import org.hibernate.internal.HEMLogging; import org.hibernate.internal.HEMLogging;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.EmptyIterator;
import org.hibernate.jpa.QueryHints; import org.hibernate.jpa.QueryHints;
import org.hibernate.jpa.TypedParameterValue; import org.hibernate.jpa.TypedParameterValue;
import org.hibernate.jpa.graph.internal.EntityGraphImpl; import org.hibernate.jpa.graph.internal.EntityGraphImpl;
@ -815,7 +817,7 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public QueryImplementor setMaxResults(int maxResult) { public QueryImplementor setMaxResults(int maxResult) {
if ( maxResult <= 0 ) { if ( maxResult < 0 ) {
// treat zero and negatives specially as meaning no limit... // treat zero and negatives specially as meaning no limit...
queryOptions.setMaxRows( null ); queryOptions.setMaxRows( null );
} }
@ -1344,6 +1346,9 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected Iterator<R> doIterate() { protected Iterator<R> doIterate() {
if (getMaxResults() == 0){
return EmptyIterator.INSTANCE;
}
return getProducer().iterate( return getProducer().iterate(
queryParameterBindings.expandListValuedParameters( getQueryString(), getProducer() ), queryParameterBindings.expandListValuedParameters( getQueryString(), getProducer() ),
getQueryParameters() getQueryParameters()
@ -1367,6 +1372,9 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
} }
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) { protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
if (getMaxResults() == 0){
return EmptyScrollableResults.INSTANCE;
}
final String query = queryParameterBindings.expandListValuedParameters( getQueryString(), getProducer() ); final String query = queryParameterBindings.expandListValuedParameters( getQueryString(), getProducer() );
QueryParameters queryParameters = getQueryParameters(); QueryParameters queryParameters = getQueryParameters();
queryParameters.setScrollMode( scrollMode ); queryParameters.setScrollMode( scrollMode );
@ -1376,6 +1384,10 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Stream<R> stream() { public Stream<R> stream() {
if (getMaxResults() == 0){
final Spliterator<R> spliterator = Spliterators.emptySpliterator();
return StreamSupport.stream( spliterator, false );
}
final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY ); final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY );
final ScrollableResultsIterator<R> iterator = new ScrollableResultsIterator<>( scrollableResults ); final ScrollableResultsIterator<R> iterator = new ScrollableResultsIterator<>( scrollableResults );
final Spliterator<R> spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL ); final Spliterator<R> spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL );
@ -1417,6 +1429,9 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected List<R> doList() { protected List<R> doList() {
if ( getMaxResults() == 0 ) {
return Collections.EMPTY_LIST;
}
if ( lockOptions.getLockMode() != null && lockOptions.getLockMode() != LockMode.NONE ) { if ( lockOptions.getLockMode() != null && lockOptions.getLockMode() != LockMode.NONE ) {
if ( !getProducer().isTransactionInProgress() ) { if ( !getProducer().isTransactionInProgress() ) {
throw new TransactionRequiredException( "no transaction is in progress" ); throw new TransactionRequiredException( "no transaction is in progress" );