package org.hibernate.internal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.NoSuchElementException;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.engine.HibernateIterator;
import org.hibernate.event.spi.EventSource;
import org.hibernate.hql.internal.HolderInstantiator;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
public final class IteratorImpl implements HibernateIterator {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( IteratorImpl.class );
private ResultSet rs;
private final EventSource session;
private boolean readOnly;
private final Type[] types;
private final boolean single;
private Object currentResult;
private boolean hasNext;
private final String[][] names;
private PreparedStatement ps;
private HolderInstantiator holderInstantiator;
public IteratorImpl(
ResultSet rs,
PreparedStatement ps,
EventSource sess,
boolean readOnly,
Type[] types,
String[][] columnNames,
HolderInstantiator holderInstantiator) throws HibernateException, SQLException {
this.rs = rs;
this.ps = ps;
this.session = sess;
this.readOnly = readOnly;
this.types = types;
this.names = columnNames;
this.holderInstantiator = holderInstantiator;
single = types.length == 1;
postNext();
}
public void close() throws JDBCException {
if ( ps != null ) {
LOG.debug( "Closing iterator" );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
try {
session.getPersistenceContext().getLoadContexts().cleanup( rs );
}
catch (Throwable ignore) {
LOG.debugf( "Exception trying to cleanup load context : %s", ignore.getMessage() );
}
session.getJdbcCoordinator().afterStatementExecution();
ps = null;
rs = null;
hasNext = false;
}
}
private void postNext() throws SQLException {
LOG.debug( "Attempting to retrieve next results" );
this.hasNext = rs.next();
if ( !hasNext ) {
LOG.debug( "Exhausted results" );
close();
}
else {
LOG.debug( "Retrieved next results" );
}
}
public boolean hasNext() {
return hasNext;
}
public Object next() throws HibernateException {
if ( !hasNext ) {
throw new NoSuchElementException( "No more results" );
}
boolean sessionDefaultReadOnlyOrig = session.isDefaultReadOnly();
session.setDefaultReadOnly( readOnly );
try {
boolean isHolder = holderInstantiator.isRequired();
LOG.debugf( "Assembling results" );
if ( single && !isHolder ) {
currentResult = types[0].nullSafeGet( rs, names[0], session, null );
}
else {
Object[] currentResults = new Object[types.length];
for ( int i = 0; i < types.length; i++ ) {
currentResults[i] = types[i].nullSafeGet( rs, names[i], session, null );
}
if ( isHolder ) {
currentResult = holderInstantiator.instantiate( currentResults );
}
else {
currentResult = currentResults;
}
}
postNext();
LOG.debugf( "Returning current results" );
return currentResult;
}
catch (SQLException sqle) {
throw session.getFactory().getSQLExceptionHelper().convert(
sqle,
"could not get next iterator result"
);
}
finally {
session.setDefaultReadOnly( sessionDefaultReadOnlyOrig );
}
}
public void remove() {
if ( !single ) {
throw new UnsupportedOperationException( "Not a single column hibernate query result set" );
}
if ( currentResult == null ) {
throw new IllegalStateException( "Called Iterator.remove() before next()" );
}
if ( !( types[0] instanceof EntityType ) ) {
throw new UnsupportedOperationException( "Not an entity" );
}
session.delete(
( (EntityType) types[0] ).getAssociatedEntityName(),
currentResult,
false,
null
);
}
}