org.hibernate.internal.FetchingScrollableResultsImpl Maven / Gradle / Ivy
/*
* 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 .
*/
package org.hibernate.internal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.hql.internal.HolderInstantiator;
import org.hibernate.loader.Loader;
import org.hibernate.type.Type;
/**
* Implementation of ScrollableResults which can handle collection fetches.
*
* @author Steve Ebersole
*/
public class FetchingScrollableResultsImpl extends AbstractScrollableResults {
private Object[] currentRow;
private int currentPosition;
private Integer maxPosition;
/**
* Constructs a FetchingScrollableResultsImpl.
*
* @param rs The scrollable result set
* @param ps The prepared statement used to obtain the result set
* @param sess The originating session
* @param loader The loader
* @param queryParameters query parameters
* @param types The result types
* @param holderInstantiator Ugh
*/
public FetchingScrollableResultsImpl(
ResultSet rs,
PreparedStatement ps,
SharedSessionContractImplementor sess,
Loader loader,
QueryParameters queryParameters,
Type[] types,
HolderInstantiator holderInstantiator) {
super( rs, ps, sess, loader, queryParameters, types, holderInstantiator );
}
@Override
protected Object[] getCurrentRow() {
return currentRow;
}
@Override
public boolean next() {
if ( maxPosition != null && maxPosition <= currentPosition ) {
currentRow = null;
currentPosition = maxPosition + 1;
return false;
}
if ( isResultSetEmpty() ) {
currentRow = null;
currentPosition = 0;
return false;
}
final Object row = getLoader().loadSequentialRowsForward(
getResultSet(),
getSession(),
getQueryParameters(),
true
);
final boolean afterLast;
try {
afterLast = getResultSet().isAfterLast();
}
catch (SQLException e) {
throw getSession().getFactory().getSQLExceptionHelper().convert(
e,
"exception calling isAfterLast()"
);
}
currentPosition++;
currentRow = new Object[] {row};
if ( afterLast ) {
if ( maxPosition == null ) {
// we just hit the last position
maxPosition = currentPosition;
}
}
afterScrollOperation();
return true;
}
@Override
public boolean previous() {
if ( currentPosition <= 1 ) {
currentPosition = 0;
currentRow = null;
return false;
}
final Object loadResult = getLoader().loadSequentialRowsReverse(
getResultSet(),
getSession(),
getQueryParameters(),
false,
( maxPosition != null && currentPosition > maxPosition )
);
currentRow = new Object[] {loadResult};
currentPosition--;
afterScrollOperation();
return true;
}
@Override
public boolean scroll(int positions) {
boolean more = false;
if ( positions > 0 ) {
// scroll ahead
for ( int i = 0; i < positions; i++ ) {
more = next();
if ( !more ) {
break;
}
}
}
else if ( positions < 0 ) {
// scroll backward
for ( int i = 0; i < ( 0 - positions ); i++ ) {
more = previous();
if ( !more ) {
break;
}
}
}
else {
throw new HibernateException( "scroll(0) not valid" );
}
afterScrollOperation();
return more;
}
@Override
public boolean last() {
boolean more = false;
if ( maxPosition != null ) {
if ( currentPosition > maxPosition ) {
more = previous();
}
for ( int i = currentPosition; i < maxPosition; i++ ) {
more = next();
}
}
else {
try {
if ( isResultSetEmpty() || getResultSet().isAfterLast() ) {
// should not be able to reach last without maxPosition being set
// unless there are no results
return false;
}
while ( !getResultSet().isAfterLast() ) {
more = next();
}
}
catch (SQLException e) {
throw getSession().getFactory().getSQLExceptionHelper().convert(
e,
"exception calling isAfterLast()"
);
}
}
afterScrollOperation();
return more;
}
@Override
public boolean first() {
beforeFirst();
boolean more = next();
afterScrollOperation();
return more;
}
@Override
public void beforeFirst() {
try {
getResultSet().beforeFirst();
}
catch (SQLException e) {
throw getSession().getFactory().getSQLExceptionHelper().convert(
e,
"exception calling beforeFirst()"
);
}
currentRow = null;
currentPosition = 0;
}
@Override
public void afterLast() {
// TODO : not sure the best way to handle this.
// The non-performant way :
last();
next();
afterScrollOperation();
}
@Override
public boolean isFirst() {
return currentPosition == 1;
}
@Override
public boolean isLast() {
return maxPosition != null && currentPosition == maxPosition;
}
@Override
public int getRowNumber() {
return currentPosition;
}
@Override
public boolean setRowNumber(int rowNumber) {
if ( rowNumber == 1 ) {
return first();
}
else if ( rowNumber == -1 ) {
return last();
}
else if ( maxPosition != null && rowNumber == maxPosition ) {
return last();
}
return scroll( rowNumber - currentPosition );
}
private boolean isResultSetEmpty() {
try {
return currentPosition == 0 && !getResultSet().isBeforeFirst() && !getResultSet().isAfterLast();
}
catch (SQLException e) {
throw getSession().getFactory().getSQLExceptionHelper().convert(
e,
"Could not determine if resultset is empty due to exception calling isBeforeFirst or isAfterLast()"
);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy