HHH-9340 - Streams API for query result processing.

This commit is contained in:
Steve Ebersole 2016-05-12 21:21:31 -05:00
parent 14b34c78bd
commit 7cae5ba95b
27 changed files with 314 additions and 95 deletions

View File

@ -5,6 +5,7 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
@ -29,20 +30,26 @@ import org.hibernate.type.Type;
*
* @author Gavin King
*/
public interface ScrollableResults extends java.io.Closeable {
public interface ScrollableResults extends AutoCloseable {
/**
* Release resources immediately.
*/
void close();
/**
* Advance to the next result.
*
* @return {@code true} if there is another result
*/
public boolean next();
boolean next();
/**
* Retreat to the previous result.
*
* @return {@code true} if there is a previous result
*/
public boolean previous();
boolean previous();
/**
* Scroll the specified number of positions from the current position.
@ -51,53 +58,53 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @return {@code true} if there is a result at the new location
*/
public boolean scroll(int positions);
boolean scroll(int positions);
/**
* Go to the last result.
*
* @return {@code true} if there are any results
*/
public boolean last();
boolean last();
/**
* Go to the first result.
*
* @return {@code true} if there are any results
*/
public boolean first();
boolean first();
/**
* Go to a location just beforeQuery first result, This is the location of the cursor on a newly returned
* scrollable result.
*/
public void beforeFirst();
void beforeFirst();
/**
* Go to a location just afterQuery the last result.
*/
public void afterLast();
void afterLast();
/**
* Is this the first result?
*
* @return {@code true} if this is the first row of results, otherwise {@code false}
*/
public boolean isFirst();
boolean isFirst();
/**
* Is this the last result?
*
* @return {@code true} if this is the last row of results.
*/
public boolean isLast();
boolean isLast();
/**
* Get the current position in the results. The first position is number 0 (unlike JDBC).
*
* @return The current position number, numbered from 0; -1 indicates that there is no current row
*/
public int getRowNumber();
int getRowNumber();
/**
* Set the current position in the result set. Can be numbered from the first position (positive number) or
@ -108,19 +115,14 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @return true if there is a row at that row number
*/
public boolean setRowNumber(int rowNumber);
/**
* Release resources immediately.
*/
public void close();
boolean setRowNumber(int rowNumber);
/**
* Get the current row of results.
*
* @return The array of results
*/
public Object[] get();
Object[] get();
/**
* Get the <tt>i</tt>th object in the current row of results, without
@ -134,7 +136,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If i is an invalid index.
*/
public Object get(int i);
Object get(int i);
/**
* Get the type of the <tt>i</tt>th column of results.
@ -145,7 +147,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If i is an invalid index.
*/
public Type getType(int i);
Type getType(int i);
/**
* Convenience method to read an integer.
@ -156,7 +158,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Integer getInteger(int col);
Integer getInteger(int col);
/**
* Convenience method to read a long.
@ -167,7 +169,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Long getLong(int col);
Long getLong(int col);
/**
* Convenience method to read a float.
@ -178,7 +180,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Float getFloat(int col);
Float getFloat(int col);
/**
* Convenience method to read a boolean.
@ -189,7 +191,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Boolean getBoolean(int col);
Boolean getBoolean(int col);
/**
* Convenience method to read a double.
@ -200,7 +202,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Double getDouble(int col);
Double getDouble(int col);
/**
* Convenience method to read a short.
@ -211,7 +213,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Short getShort(int col);
Short getShort(int col);
/**
* Convenience method to read a byte.
@ -222,7 +224,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Byte getByte(int col);
Byte getByte(int col);
/**
* Convenience method to read a char.
@ -233,7 +235,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Character getCharacter(int col);
Character getCharacter(int col);
/**
* Convenience method to read a binary (byte[]).
@ -244,7 +246,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public byte[] getBinary(int col);
byte[] getBinary(int col);
/**
* Convenience method to read a String using streaming.
@ -255,7 +257,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public String getText(int col);
String getText(int col);
/**
* Convenience method to read a blob.
@ -266,7 +268,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Blob getBlob(int col);
Blob getBlob(int col);
/**
* Convenience method to read a clob.
@ -277,7 +279,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Clob getClob(int col);
Clob getClob(int col);
/**
* Convenience method to read a string.
@ -288,7 +290,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public String getString(int col);
String getString(int col);
/**
* Convenience method to read a BigDecimal.
@ -299,7 +301,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public BigDecimal getBigDecimal(int col);
BigDecimal getBigDecimal(int col);
/**
* Convenience method to read a BigInteger.
@ -310,7 +312,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public BigInteger getBigInteger(int col);
BigInteger getBigInteger(int col);
/**
* Convenience method to read a Date.
@ -321,7 +323,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Date getDate(int col);
Date getDate(int col);
/**
* Convenience method to read a Locale.
@ -332,7 +334,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Locale getLocale(int col);
Locale getLocale(int col);
/**
* Convenience method to read a Calendar.
@ -343,7 +345,7 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public Calendar getCalendar(int col);
Calendar getCalendar(int col);
/**
* Convenience method to read a TimeZone.
@ -354,5 +356,5 @@ public interface ScrollableResults extends java.io.Closeable {
*
* @throws IndexOutOfBoundsException If col is an invalid index.
*/
public TimeZone getTimeZone(int col);
TimeZone getTimeZone(int col);
}

View File

@ -80,7 +80,7 @@ import org.hibernate.stat.SessionStatistics;
* @author Gavin King
* @author Steve Ebersole
*/
public interface Session extends SharedSessionContract, EntityManager, HibernateEntityManager, java.io.Closeable {
public interface Session extends SharedSessionContract, EntityManager, HibernateEntityManager, AutoCloseable {
/**
* Obtain a {@link Session} builder with the ability to grab certain information from this session.
*

View File

@ -25,11 +25,11 @@ import java.sql.Connection;
*
* @author Gavin King
*/
public interface StatelessSession extends SharedSessionContract, java.io.Closeable {
public interface StatelessSession extends SharedSessionContract, AutoCloseable {
/**
* Close the stateless session and release the JDBC connection.
*/
public void close();
void close();
/**
* Insert a row.
@ -38,7 +38,7 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
*
* @return The identifier of the inserted entity
*/
public Serializable insert(Object entity);
Serializable insert(Object entity);
/**
* Insert a row.
@ -48,14 +48,14 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
*
* @return the identifier of the instance
*/
public Serializable insert(String entityName, Object entity);
Serializable insert(String entityName, Object entity);
/**
* Update a row.
*
* @param entity a detached entity instance
*/
public void update(Object entity);
void update(Object entity);
/**
* Update a row.
@ -63,14 +63,14 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
* @param entityName The entityName for the entity to be updated
* @param entity a detached entity instance
*/
public void update(String entityName, Object entity);
void update(String entityName, Object entity);
/**
* Delete a row.
*
* @param entity a detached entity instance
*/
public void delete(Object entity);
void delete(Object entity);
/**
* Delete a row.
@ -78,7 +78,7 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
* @param entityName The entityName for the entity to be deleted
* @param entity a detached entity instance
*/
public void delete(String entityName, Object entity);
void delete(String entityName, Object entity);
/**
* Retrieve a row.
@ -88,7 +88,7 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
*
* @return a detached entity instance
*/
public Object get(String entityName, Serializable id);
Object get(String entityName, Serializable id);
/**
* Retrieve a row.
@ -98,7 +98,7 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
*
* @return a detached entity instance
*/
public Object get(Class entityClass, Serializable id);
Object get(Class entityClass, Serializable id);
/**
* Retrieve a row, obtaining the specified lock mode.
@ -109,7 +109,7 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
*
* @return a detached entity instance
*/
public Object get(String entityName, Serializable id, LockMode lockMode);
Object get(String entityName, Serializable id, LockMode lockMode);
/**
* Retrieve a row, obtaining the specified lock mode.
@ -120,14 +120,14 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
*
* @return a detached entity instance
*/
public Object get(Class entityClass, Serializable id, LockMode lockMode);
Object get(Class entityClass, Serializable id, LockMode lockMode);
/**
* Refresh the entity instance state from the database.
*
* @param entity The entity to be refreshed.
*/
public void refresh(Object entity);
void refresh(Object entity);
/**
* Refresh the entity instance state from the database.
@ -135,7 +135,7 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
* @param entityName The entityName for the entity to be refreshed.
* @param entity The entity to be refreshed.
*/
public void refresh(String entityName, Object entity);
void refresh(String entityName, Object entity);
/**
* Refresh the entity instance state from the database.
@ -143,7 +143,7 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
* @param entity The entity to be refreshed.
* @param lockMode The LockMode to be applied.
*/
public void refresh(Object entity, LockMode lockMode);
void refresh(Object entity, LockMode lockMode);
/**
* Refresh the entity instance state from the database.
@ -152,7 +152,7 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
* @param entity The entity to be refreshed.
* @param lockMode The LockMode to be applied.
*/
public void refresh(String entityName, Object entity, LockMode lockMode);
void refresh(String entityName, Object entity, LockMode lockMode);
/**
* Returns the current JDBC connection associated with this
@ -168,5 +168,5 @@ public interface StatelessSession extends SharedSessionContract, java.io.Closeab
* @return The connection associated with this stateless session
*/
@Deprecated
public Connection connection();
Connection connection();
}

View File

@ -18,11 +18,11 @@ import org.hibernate.JDBCException;
*
* @author Gavin King
*/
public interface HibernateIterator extends Iterator, java.io.Closeable {
public interface HibernateIterator extends Iterator, AutoCloseable {
/**
* Close the Hibernate query result iterator
*
* @throws JDBCException Indicates a problem releasing the underlying JDBC resources.
*/
public void close() throws JDBCException;
void close() throws JDBCException;
}

View File

@ -36,6 +36,7 @@ import org.hibernate.internal.util.collections.EmptyIterator;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.internal.util.collections.JoinedIterator;
import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.type.Type;
/**
@ -333,7 +334,7 @@ public class HQLQueryPlan implements Serializable {
*
* @throws HibernateException Indicates a problem performing the query
*/
public ScrollableResults performScroll(
public ScrollableResultsImplementor performScroll(
QueryParameters queryParameters,
SharedSessionContractImplementor session) throws HibernateException {
if ( traceEnabled ) {

View File

@ -39,12 +39,10 @@ import org.hibernate.MultiIdentifierLoadAccess;
import org.hibernate.NaturalIdLoadAccess;
import org.hibernate.ReplicationMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionEventListener;
import org.hibernate.SharedSessionBuilder;
import org.hibernate.SimpleNaturalIdLoadAccess;
import org.hibernate.StaleStateException;
import org.hibernate.Transaction;
import org.hibernate.TypeHelper;
import org.hibernate.UnknownProfileException;
@ -61,6 +59,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.query.spi.NativeQueryImplementor;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
import org.hibernate.stat.SessionStatistics;
@ -199,12 +198,12 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
}
@Override
public ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException {
public ScrollableResultsImplementor scroll(String query, QueryParameters queryParameters) throws HibernateException {
return delegate.scroll( query, queryParameters );
}
@Override
public ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode) {
public ScrollableResultsImplementor scroll(Criteria criteria, ScrollMode scrollMode) {
return delegate.scroll( criteria, scrollMode );
}
@ -259,7 +258,7 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
}
@Override
public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) throws HibernateException {
public ScrollableResultsImplementor scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) throws HibernateException {
return delegate.scrollCustomQuery( customQuery, queryParameters );
}
@ -269,7 +268,7 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
}
@Override
public ScrollableResults scroll(NativeSQLQuerySpecification spec, QueryParameters queryParameters) throws HibernateException {
public ScrollableResultsImplementor scroll(NativeSQLQuerySpecification spec, QueryParameters queryParameters) throws HibernateException {
return delegate.scroll( spec, queryParameters );
}

View File

@ -30,6 +30,7 @@ import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.spi.QueryProducerImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.resource.jdbc.spi.JdbcSessionOwner;
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
@ -223,12 +224,12 @@ public interface SharedSessionContractImplementor
/**
* Execute a <tt>scroll()</tt> query
*/
ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException;
ScrollableResultsImplementor scroll(String query, QueryParameters queryParameters) throws HibernateException;
/**
* Execute a criteria query
*/
ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode);
ScrollableResultsImplementor scroll(Criteria criteria, ScrollMode scrollMode);
/**
* Execute a criteria query
@ -290,7 +291,7 @@ public interface SharedSessionContractImplementor
/**
* Execute an SQL Query
*/
ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
ScrollableResultsImplementor scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
throws HibernateException;
/**
@ -316,7 +317,7 @@ public interface SharedSessionContractImplementor
*
* @throws HibernateException
*/
ScrollableResults scroll(NativeSQLQuerySpecification spec, QueryParameters queryParameters);
ScrollableResultsImplementor scroll(NativeSQLQuerySpecification spec, QueryParameters queryParameters);
int getDontFlushFromFind();

View File

@ -52,6 +52,7 @@ import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.loader.hql.QueryLoader;
import org.hibernate.param.ParameterSpecification;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
@ -416,7 +417,7 @@ public class QueryTranslatorImpl implements FilterTranslator {
* Return the query results, as an instance of <tt>ScrollableResults</tt>
*/
@Override
public ScrollableResults scroll(QueryParameters queryParameters, SharedSessionContractImplementor session)
public ScrollableResultsImplementor scroll(QueryParameters queryParameters, SharedSessionContractImplementor session)
throws HibernateException {
// Delegate to the QueryLoader...
errorIfDML();

View File

@ -53,6 +53,7 @@ import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.JoinType;
import org.hibernate.sql.QuerySelect;
@ -1219,7 +1220,7 @@ public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator
}
@Override
public ScrollableResults scroll(
public ScrollableResultsImplementor scroll(
final QueryParameters queryParameters,
final SharedSessionContractImplementor session) throws HibernateException {
HolderInstantiator hi = HolderInstantiator.createClassicHolderInstantiator(

View File

@ -19,6 +19,7 @@ import org.hibernate.ScrollableResults;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.spi.EventSource;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.type.Type;
/**
@ -73,7 +74,7 @@ public interface QueryTranslator {
* @return The ScrollableResults wrapper around the query results.
* @throws HibernateException
*/
ScrollableResults scroll(QueryParameters queryParameters, SharedSessionContractImplementor session)
ScrollableResultsImplementor scroll(QueryParameters queryParameters, SharedSessionContractImplementor session)
throws HibernateException;
/**

View File

@ -18,11 +18,11 @@ import java.util.Locale;
import java.util.TimeZone;
import org.hibernate.HibernateException;
import org.hibernate.ScrollableResults;
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.query.spi.ScrollableResultsImplementor;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
@ -31,7 +31,7 @@ import org.hibernate.type.Type;
*
* @author Steve Ebersole
*/
public abstract class AbstractScrollableResults implements ScrollableResults {
public abstract class AbstractScrollableResults implements ScrollableResultsImplementor {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractScrollableResults.class );
private final ResultSet resultSet;
@ -41,6 +41,7 @@ public abstract class AbstractScrollableResults implements ScrollableResults {
private final QueryParameters queryParameters;
private final Type[] types;
private HolderInstantiator holderInstantiator;
private boolean closed;
protected AbstractScrollableResults(
ResultSet rs,
@ -93,6 +94,11 @@ public abstract class AbstractScrollableResults implements ScrollableResults {
@Override
public final void close() {
if ( this.closed ) {
// noop if already closed
return;
}
// not absolutely necessary, but does help with aggressive release
//session.getJDBCContext().getConnectionManager().closeQueryStatement( ps, resultSet );
session.getJdbcCoordinator().getResourceRegistry().release( ps );
@ -106,15 +112,28 @@ public abstract class AbstractScrollableResults implements ScrollableResults {
LOG.tracev( "Exception trying to cleanup load context : {0}", ignore.getMessage() );
}
}
this.closed = true;
}
@Override
public boolean isClosed() {
return this.closed;
}
@Override
public final Object[] get() throws HibernateException {
if ( closed ) {
throw new IllegalStateException( "ScrollableResults is closed" );
}
return getCurrentRow();
}
@Override
public final Object get(int col) throws HibernateException {
if ( closed ) {
throw new IllegalStateException( "ScrollableResults is closed" );
}
return getCurrentRow()[col];
}
@ -127,6 +146,10 @@ public abstract class AbstractScrollableResults implements ScrollableResults {
* @param returnType a "final" type
*/
protected final Object getFinal(int col, Type returnType) throws HibernateException {
if ( closed ) {
throw new IllegalStateException( "ScrollableResults is closed" );
}
if ( holderInstantiator != null ) {
throw new HibernateException( "query specifies a holder class" );
}
@ -148,6 +171,10 @@ public abstract class AbstractScrollableResults implements ScrollableResults {
* @param returnType any type
*/
protected final Object getNonFinal(int col, Type returnType) throws HibernateException {
if ( closed ) {
throw new IllegalStateException( "ScrollableResults is closed" );
}
if ( holderInstantiator != null ) {
throw new HibernateException( "query specifies a holder class" );
}

View File

@ -25,8 +25,6 @@ public abstract class AbstractSessionImpl
implements Serializable, SharedSessionContractImplementor, JdbcSessionOwner, SessionImplementor, EventSource,
Options, WrapperOptions {
private static final CoreMessageLogger log = CoreLogging.messageLogger( AbstractSessionImpl.class );
protected AbstractSessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
super( factory, options );
}

View File

@ -72,6 +72,7 @@ import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.query.internal.QueryImpl;
import org.hibernate.query.spi.NativeQueryImplementor;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
@ -948,7 +949,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
@Override
public ScrollableResults scroll(NativeSQLQuerySpecification spec, QueryParameters queryParameters) {
public ScrollableResultsImplementor scroll(NativeSQLQuerySpecification spec, QueryParameters queryParameters) {
return scrollCustomQuery( getNativeQueryPlan( spec ).getCustomQuery(), queryParameters );
}

View File

@ -169,6 +169,7 @@ import org.hibernate.query.criteria.internal.compile.CriteriaCompiler;
import org.hibernate.query.criteria.internal.expression.CompoundSelectionImpl;
import org.hibernate.query.internal.CollectionFilterImpl;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.resource.transaction.TransactionRequiredForJoinException;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl;
import org.hibernate.resource.transaction.backend.jta.internal.synchronization.AfterCompletionAction;
@ -1525,7 +1526,7 @@ public final class SessionImpl
}
@Override
public ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException {
public ScrollableResultsImplementor scroll(String query, QueryParameters queryParameters) throws HibernateException {
checkOpen();
checkTransactionSynchStatus();
@ -1782,7 +1783,7 @@ public final class SessionImpl
}
@Override
public ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode) {
public ScrollableResultsImplementor scroll(Criteria criteria, ScrollMode scrollMode) {
// TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
@ -2074,7 +2075,7 @@ public final class SessionImpl
}
@Override
public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) {
public ScrollableResultsImplementor scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters) {
checkOpen();
// checkTransactionSynchStatus();

View File

@ -46,6 +46,7 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.spi.ScrollableResultsImplementor;
/**
* @author Gavin King
@ -498,7 +499,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
}
@Override
public ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode) {
public ScrollableResultsImplementor scroll(Criteria criteria, ScrollMode scrollMode) {
// TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
@ -581,7 +582,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
}
@Override
public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
public ScrollableResultsImplementor scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
throws HibernateException {
checkOpen();
CustomLoader loader = new CustomLoader( customQuery, getFactory() );
@ -589,7 +590,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
}
@Override
public ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException {
public ScrollableResultsImplementor scroll(String query, QueryParameters queryParameters) throws HibernateException {
checkOpen();
HQLQueryPlan plan = getQueryPlan( query, false );
return plan.performScroll( queryParameters, this );

View File

@ -74,6 +74,7 @@ import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.transform.CacheableResultTransformer;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.AssociationType;
@ -2668,7 +2669,7 @@ public abstract class Loader {
* @throws HibernateException Indicates an error executing the query, or constructing
* the ScrollableResults.
*/
protected ScrollableResults scroll(
protected ScrollableResultsImplementor scroll(
final QueryParameters queryParameters,
final Type[] returnTypes,
final HolderInstantiator holderInstantiator,

View File

@ -33,6 +33,7 @@ import org.hibernate.loader.spi.AfterLoadAction;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.Type;
@ -97,7 +98,7 @@ public class CriteriaLoader extends OuterJoinLoader {
}
public ScrollableResults scroll(SharedSessionContractImplementor session, ScrollMode scrollMode)
public ScrollableResultsImplementor scroll(SharedSessionContractImplementor session, ScrollMode scrollMode)
throws HibernateException {
QueryParameters qp = translator.getQueryParameters();
qp.setScrollMode( scrollMode );

View File

@ -38,6 +38,7 @@ import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.CollectionType;
import org.hibernate.type.EntityType;
@ -369,7 +370,7 @@ public class CustomLoader extends Loader {
return sql;
}
public ScrollableResults scroll(final QueryParameters queryParameters, final SharedSessionContractImplementor session)
public ScrollableResultsImplementor scroll(final QueryParameters queryParameters, final SharedSessionContractImplementor session)
throws HibernateException {
return scroll(
queryParameters,

View File

@ -43,6 +43,7 @@ import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
@ -563,7 +564,7 @@ public class QueryLoader extends BasicLoader {
}
public ScrollableResults scroll(
public ScrollableResultsImplementor scroll(
final QueryParameters queryParameters,
final SharedSessionContractImplementor session) throws HibernateException {
checkQuery( queryParameters );

View File

@ -12,6 +12,8 @@ import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.Spliterator;
import java.util.stream.Stream;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.Parameter;
@ -48,12 +50,26 @@ public interface Query<R> extends TypedQuery<R>, org.hibernate.Query<R>, BasicQu
/**
* "QueryOptions" is a better name, I think, than "RowSelection" -> 6.0
*
* @todo 6.0 rename RowSelection to QueryOptions
*
* @return Return the encapsulation of this query's options, which includes access to
* firstRow, maxRows, timeout and fetchSize. Important because this gives access to
* those values in their Integer form rather than the primitive form (int) required by JPA.
*/
RowSelection getQueryOptions();
/**
* Retrieve a Stream over the query results.
* <p/>
* In the initial implementation (5.2) this returns a simple sequential Stream. The plan
* is to return a a smarter stream in 6.0 leveraging the SQM model.
*
* @return The results Stream
*
* @since 5.2
*/
Stream<R> stream();
Query<R> setParameter(Parameter<Instant> param, Instant value, TemporalType temporalType);
Query<R> setParameter(Parameter<LocalDateTime> param, LocalDateTime value, TemporalType temporalType);

View File

@ -22,6 +22,10 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.persistence.CacheRetrieveMode;
import javax.persistence.CacheStoreMode;
import javax.persistence.FlushModeType;
@ -39,7 +43,6 @@ import org.hibernate.LockOptions;
import org.hibernate.NonUniqueResultException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.TypeMismatchException;
import org.hibernate.engine.query.spi.EntityGraphQueryHint;
import org.hibernate.engine.query.spi.HQLQueryPlan;
@ -67,6 +70,7 @@ import org.hibernate.query.QueryParameter;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterListBinding;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.Type;
@ -1284,12 +1288,12 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
}
@Override
public ScrollableResults scroll() {
public ScrollableResultsImplementor scroll() {
return scroll( getProducer().getJdbcServices().getJdbcEnvironment().getDialect().defaultScrollMode() );
}
@Override
public ScrollableResults scroll(ScrollMode scrollMode) {
public ScrollableResultsImplementor scroll(ScrollMode scrollMode) {
beforeQuery();
try {
return doScroll( scrollMode );
@ -1299,7 +1303,7 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
}
}
protected ScrollableResults doScroll(ScrollMode scrollMode) {
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
QueryParameters queryParameters = getQueryParameters();
queryParameters.setScrollMode( scrollMode );
return getProducer().scroll(
@ -1308,6 +1312,19 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
);
}
@Override
@SuppressWarnings("unchecked")
public Stream<R> stream() {
final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY );
final ScrollableResultsIterator<R> iterator = new ScrollableResultsIterator<>( scrollableResults );
final Spliterator<R> spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL );
final Stream<R> stream = StreamSupport.stream( spliterator, false );
stream.onClose( scrollableResults::close );
return stream;
}
@Override
public List<R> list() {
beforeQuery();

View File

@ -14,6 +14,7 @@ import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.Query;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.type.Type;
/**
@ -66,12 +67,12 @@ public class CollectionFilterImpl extends org.hibernate.query.internal.AbstractP
}
@Override
public ScrollableResults scroll() throws HibernateException {
public ScrollableResultsImplementor scroll() throws HibernateException {
throw new UnsupportedOperationException( "Can't scroll filters" );
}
@Override
public ScrollableResults scroll(ScrollMode scrollMode) {
public ScrollableResultsImplementor scroll(ScrollMode scrollMode) {
throw new UnsupportedOperationException( "Can't scroll filters" );
}

View File

@ -40,6 +40,7 @@ import org.hibernate.query.NativeQuery;
import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.spi.NativeQueryImplementor;
import org.hibernate.query.spi.ScrollableResultsImplementor;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.Type;
@ -183,7 +184,7 @@ public class NativeQueryImpl<T> extends AbstractProducedQuery<T> implements Nati
}
@Override
protected ScrollableResults doScroll(ScrollMode scrollMode) {
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
return getProducer().scroll(
generateQuerySpecification(),
getQueryParameters()

View File

@ -0,0 +1,41 @@
/*
* 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.query.internal;
import org.hibernate.Incubating;
import org.hibernate.query.spi.CloseableIterator;
import org.hibernate.query.spi.ScrollableResultsImplementor;
/**
* @author Steve Ebersole
*
* @since 5.2
*/
@Incubating
public class ScrollableResultsIterator<T> implements CloseableIterator {
private final ScrollableResultsImplementor scrollableResults;
public ScrollableResultsIterator(ScrollableResultsImplementor scrollableResults) {
this.scrollableResults = scrollableResults;
}
@Override
public void close() {
scrollableResults.close();
}
@Override
public boolean hasNext() {
return !scrollableResults.isClosed() && scrollableResults.next();
}
@Override
@SuppressWarnings("unchecked")
public T next() {
return (T) scrollableResults.get();
}
}

View File

@ -0,0 +1,24 @@
/*
* 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.query.spi;
import java.util.Iterator;
import org.hibernate.Incubating;
/**
* Unification of Iterator and AutoCloseable
*
* @author Steve Ebersole
*
* @since 5.2
*/
@Incubating
public interface CloseableIterator<T> extends Iterator<T>, AutoCloseable {
@Override
void close();
}

View File

@ -0,0 +1,20 @@
/*
* 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.query.spi;
import org.hibernate.Incubating;
import org.hibernate.ScrollableResults;
/**
* @author Steve Ebersole
*
* @since 5.2
*/
@Incubating
public interface ScrollableResultsImplementor extends ScrollableResults {
boolean isClosed();
}

View File

@ -0,0 +1,61 @@
/*
* 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.test.stream.basic;
import java.util.stream.Stream;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.Session;
import org.hibernate.boot.MetadataSources;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
/**
* @author Steve Ebersole
*/
public class BasicStreamTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected void applyMetadataSources(MetadataSources metadataSources) {
super.applyMetadataSources( metadataSources );
metadataSources.addAnnotatedClass( MyEntity.class );
}
@Test
public void basicStreamTest() {
Session session = openSession();
session.getTransaction().begin();
// mainly we want to make sure that closing the Stream releases the ScrollableResults too
assertThat( ( (SessionImplementor) session ).getJdbcCoordinator().getLogicalConnection().getResourceRegistry().hasRegisteredResources(), is( false ) );
final Stream<MyEntity> stream = session.createQuery( "from MyEntity", MyEntity.class ).stream();
assertThat( ( (SessionImplementor) session ).getJdbcCoordinator().getLogicalConnection().getResourceRegistry().hasRegisteredResources(), is( true ) );
stream.forEach( System.out::println );
assertThat( ( (SessionImplementor) session ).getJdbcCoordinator().getLogicalConnection().getResourceRegistry().hasRegisteredResources(), is( true ) );
stream.close();
assertThat( ( (SessionImplementor) session ).getJdbcCoordinator().getLogicalConnection().getResourceRegistry().hasRegisteredResources(), is( false ) );
session.getTransaction().commit();
session.close();
}
@Entity(name = "MyEntity")
@Table(name="MyEntity")
public static class MyEntity {
@Id
public Integer id;
public String name;
}
}