From 6062eb67ea7f34ac66104a0b57f1edad681eaec0 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 14 Jan 2013 14:24:45 -0600 Subject: [PATCH] HHH-7914 - Improve new stored procedure call support --- .../org/hibernate/SharedSessionContract.java | 8 +- .../internal/AbstractSessionImpl.java | 22 +-- .../org/hibernate/internal/SessionImpl.java | 10 +- .../{Call.java => ProcedureCall.java} | 14 +- .../{Outputs.java => ProcedureResult.java} | 30 ++-- .../AbstractParameterRegistrationImpl.java | 12 +- .../internal/NamedParameterRegistration.java | 2 +- .../PositionalParameterRegistration.java | 2 +- .../{CallImpl.java => ProcedureCallImpl.java} | 70 +++++----- .../internal/ProcedureResultImpl.java | 116 ++++++++++++++++ .../org/hibernate/procedure/package-info.java | 20 +-- .../NoMoreReturnsException.java} | 9 +- .../Result.java} | 24 +++- .../ResultSetReturn.java | 4 +- .../{procedure => result}/Return.java | 4 +- .../UpdateCountReturn.java | 4 +- .../internal/ResultImpl.java} | 130 +++++++----------- .../org/hibernate/result/package-info.java | 24 ++++ .../spi/ResultContext.java} | 18 ++- .../sql/storedproc/StoredProcedureTest.java | 60 ++++---- .../internal/StoredProcedureQueryImpl.java | 24 ++-- .../jpa/spi/AbstractEntityManagerImpl.java | 10 +- 22 files changed, 380 insertions(+), 237 deletions(-) rename hibernate-core/src/main/java/org/hibernate/procedure/{Call.java => ProcedureCall.java} (87%) rename hibernate-core/src/main/java/org/hibernate/procedure/{Outputs.java => ProcedureResult.java} (71%) rename hibernate-core/src/main/java/org/hibernate/procedure/internal/{CallImpl.java => ProcedureCallImpl.java} (84%) create mode 100644 hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureResultImpl.java rename hibernate-core/src/main/java/org/hibernate/{procedure/InOutParameterRegistration.java => result/NoMoreReturnsException.java} (83%) rename hibernate-core/src/main/java/org/hibernate/{procedure/OutParameterRegistration.java => result/Result.java} (55%) rename hibernate-core/src/main/java/org/hibernate/{procedure => result}/ResultSetReturn.java (94%) rename hibernate-core/src/main/java/org/hibernate/{procedure => result}/Return.java (91%) rename hibernate-core/src/main/java/org/hibernate/{procedure => result}/UpdateCountReturn.java (92%) rename hibernate-core/src/main/java/org/hibernate/{procedure/internal/OutputsImpl.java => result/internal/ResultImpl.java} (59%) create mode 100644 hibernate-core/src/main/java/org/hibernate/result/package-info.java rename hibernate-core/src/main/java/org/hibernate/{procedure/InParameterRegistration.java => result/spi/ResultContext.java} (67%) diff --git a/hibernate-core/src/main/java/org/hibernate/SharedSessionContract.java b/hibernate-core/src/main/java/org/hibernate/SharedSessionContract.java index 2a704629cf..cc3692194e 100644 --- a/hibernate-core/src/main/java/org/hibernate/SharedSessionContract.java +++ b/hibernate-core/src/main/java/org/hibernate/SharedSessionContract.java @@ -25,7 +25,7 @@ package org.hibernate; import java.io.Serializable; -import org.hibernate.procedure.Call; +import org.hibernate.procedure.ProcedureCall; /** * Contract methods shared between {@link Session} and {@link StatelessSession} @@ -93,7 +93,7 @@ public interface SharedSessionContract extends Serializable { * * @return The representation of the procedure call. */ - public Call createStoredProcedureCall(String procedureName); + public ProcedureCall createStoredProcedureCall(String procedureName); /** * Creates a call to a stored procedure with specific result set entity mappings. Each class named @@ -104,7 +104,7 @@ public interface SharedSessionContract extends Serializable { * * @return The representation of the procedure call. */ - public Call createStoredProcedureCall(String procedureName, Class... resultClasses); + public ProcedureCall createStoredProcedureCall(String procedureName, Class... resultClasses); /** * Creates a call to a stored procedure with specific result set entity mappings @@ -114,7 +114,7 @@ public interface SharedSessionContract extends Serializable { * * @return The representation of the procedure call. */ - public Call createStoredProcedureCall(String procedureName, String... resultSetMappings); + public ProcedureCall createStoredProcedureCall(String procedureName, String... resultSetMappings); /** * Create {@link Criteria} instance for the given class (entity or subclasses/implementors) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSessionImpl.java index 072a162fe9..c6b0153c74 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSessionImpl.java @@ -37,7 +37,7 @@ import org.hibernate.SQLQuery; import org.hibernate.ScrollableResults; import org.hibernate.SessionException; import org.hibernate.SharedSessionContract; -import org.hibernate.procedure.Call; +import org.hibernate.procedure.ProcedureCall; import org.hibernate.cache.spi.CacheKey; import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess; @@ -59,7 +59,7 @@ import org.hibernate.jdbc.WorkExecutorVisitable; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider; -import org.hibernate.procedure.internal.CallImpl; +import org.hibernate.procedure.internal.ProcedureCallImpl; import org.hibernate.type.Type; /** @@ -241,29 +241,29 @@ public abstract class AbstractSessionImpl implements Serializable, SharedSession @Override @SuppressWarnings("UnnecessaryLocalVariable") - public Call createStoredProcedureCall(String procedureName) { + public ProcedureCall createStoredProcedureCall(String procedureName) { errorIfClosed(); - final Call call = new CallImpl( this, procedureName ); + final ProcedureCall procedureCall = new ProcedureCallImpl( this, procedureName ); // call.setComment( "Dynamic stored procedure call" ); - return call; + return procedureCall; } @Override @SuppressWarnings("UnnecessaryLocalVariable") - public Call createStoredProcedureCall(String procedureName, Class... resultClasses) { + public ProcedureCall createStoredProcedureCall(String procedureName, Class... resultClasses) { errorIfClosed(); - final Call call = new CallImpl( this, procedureName, resultClasses ); + final ProcedureCall procedureCall = new ProcedureCallImpl( this, procedureName, resultClasses ); // call.setComment( "Dynamic stored procedure call" ); - return call; + return procedureCall; } @Override @SuppressWarnings("UnnecessaryLocalVariable") - public Call createStoredProcedureCall(String procedureName, String... resultSetMappings) { + public ProcedureCall createStoredProcedureCall(String procedureName, String... resultSetMappings) { errorIfClosed(); - final Call call = new CallImpl( this, procedureName, resultSetMappings ); + final ProcedureCall procedureCall = new ProcedureCallImpl( this, procedureName, resultSetMappings ); // call.setComment( "Dynamic stored procedure call" ); - return call; + return procedureCall; } protected HQLQueryPlan getHQLQueryPlan(String query, boolean shallow) throws HibernateException { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index c625d76461..7030f5d3c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -74,6 +74,8 @@ import org.hibernate.ScrollableResults; import org.hibernate.Session; import org.hibernate.SessionBuilder; import org.hibernate.SessionException; +import org.hibernate.procedure.ProcedureCall; +import org.hibernate.engine.spi.SessionOwner; import org.hibernate.SharedSessionBuilder; import org.hibernate.SimpleNaturalIdLoadAccess; import org.hibernate.Transaction; @@ -98,7 +100,6 @@ import org.hibernate.engine.spi.NonFlushedChanges; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.SessionOwner; import org.hibernate.engine.spi.Status; import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl; import org.hibernate.engine.transaction.spi.TransactionCoordinator; @@ -149,7 +150,6 @@ import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.pretty.MessageHelper; -import org.hibernate.procedure.Call; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.stat.SessionStatistics; @@ -1742,21 +1742,21 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc } @Override - public Call createStoredProcedureCall(String procedureName) { + public ProcedureCall createStoredProcedureCall(String procedureName) { errorIfClosed(); checkTransactionSynchStatus(); return super.createStoredProcedureCall( procedureName ); } @Override - public Call createStoredProcedureCall(String procedureName, String... resultSetMappings) { + public ProcedureCall createStoredProcedureCall(String procedureName, String... resultSetMappings) { errorIfClosed(); checkTransactionSynchStatus(); return super.createStoredProcedureCall( procedureName, resultSetMappings ); } @Override - public Call createStoredProcedureCall(String procedureName, Class... resultClasses) { + public ProcedureCall createStoredProcedureCall(String procedureName, Class... resultClasses) { errorIfClosed(); checkTransactionSynchStatus(); return super.createStoredProcedureCall( procedureName, resultClasses ); diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/Call.java b/hibernate-core/src/main/java/org/hibernate/procedure/ProcedureCall.java similarity index 87% rename from hibernate-core/src/main/java/org/hibernate/procedure/Call.java rename to hibernate-core/src/main/java/org/hibernate/procedure/ProcedureCall.java index dbe02e713d..3ad02c4013 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/Call.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/ProcedureCall.java @@ -35,15 +35,15 @@ import org.hibernate.SynchronizeableQuery; * * @author Steve Ebersole */ -public interface Call extends BasicQueryContract, SynchronizeableQuery { +public interface ProcedureCall extends BasicQueryContract, SynchronizeableQuery { @Override - public Call addSynchronizedQuerySpace(String querySpace); + public ProcedureCall addSynchronizedQuerySpace(String querySpace); @Override - public Call addSynchronizedEntityName(String entityName) throws MappingException; + public ProcedureCall addSynchronizedEntityName(String entityName) throws MappingException; @Override - public Call addSynchronizedEntityClass(Class entityClass) throws MappingException; + public ProcedureCall addSynchronizedEntityClass(Class entityClass) throws MappingException; /** * Get the name of the stored procedure to be called. @@ -72,7 +72,7 @@ public interface Call extends BasicQueryContract, SynchronizeableQuery { * * @return {@code this}, for method chaining */ - public Call registerParameter0(int position, Class type, ParameterMode mode); + public ProcedureCall registerParameter0(int position, Class type, ParameterMode mode); /** * Retrieve a previously registered parameter memento by the position under which it was registered. @@ -104,7 +104,7 @@ public interface Call extends BasicQueryContract, SynchronizeableQuery { * * @return The parameter registration memento */ - public Call registerParameter0(String parameterName, Class type, ParameterMode mode) + public ProcedureCall registerParameter0(String parameterName, Class type, ParameterMode mode) throws NamedParametersNotSupportedException; /** @@ -131,6 +131,6 @@ public interface Call extends BasicQueryContract, SynchronizeableQuery { * * @return The outputs representation */ - public Outputs getOutputs(); + public ProcedureResult getResult(); } diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/Outputs.java b/hibernate-core/src/main/java/org/hibernate/procedure/ProcedureResult.java similarity index 71% rename from hibernate-core/src/main/java/org/hibernate/procedure/Outputs.java rename to hibernate-core/src/main/java/org/hibernate/procedure/ProcedureResult.java index 115aea7304..c680d9e39e 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/Outputs.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/ProcedureResult.java @@ -23,14 +23,15 @@ */ package org.hibernate.procedure; +import org.hibernate.result.Result; + /** - * Represents all the outputs of a call to a database stored procedure (or function) through the JDBC - * {@link java.sql.CallableStatement} interface. + * Specialization of the {@link Result} contract providing access to the stored procedure's registered + * output parameters. * * @author Steve Ebersole */ -public interface Outputs { - +public interface ProcedureResult extends Result { /** * Retrieve the value of an OUTPUT parameter by the parameter's registration memento. *

@@ -41,7 +42,7 @@ public interface Outputs { * * @return The output value. * - * @see Call#registerParameter(String, Class, javax.persistence.ParameterMode) + * @see ProcedureCall#registerParameter(String, Class, javax.persistence.ParameterMode) */ public T getOutputParameterValue(ParameterRegistration parameterRegistration); @@ -52,7 +53,7 @@ public interface Outputs { * * @return The output value. * - * @see Call#registerParameter(String, Class, javax.persistence.ParameterMode) + * @see ProcedureCall#registerParameter(String, Class, javax.persistence.ParameterMode) */ public Object getOutputParameterValue(String name); @@ -63,22 +64,7 @@ public interface Outputs { * * @return The output value. * - * @see Call#registerParameter(int, Class, javax.persistence.ParameterMode) + * @see ProcedureCall#registerParameter(int, Class, javax.persistence.ParameterMode) */ public Object getOutputParameterValue(int position); - - /** - * Are there any more returns associated with this set of outputs? - * - * @return {@code true} means there are more results available via {@link #getNextReturn()}; {@code false} - * indicates that calling {@link #getNextReturn()} will certainly result in an exception. - */ - public boolean hasMoreReturns(); - - /** - * Retrieve the next return. - * - * @return The next return. - */ - public Return getNextReturn(); } diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/AbstractParameterRegistrationImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/AbstractParameterRegistrationImpl.java index 50c440b983..5a75e403d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/AbstractParameterRegistrationImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/AbstractParameterRegistrationImpl.java @@ -48,7 +48,7 @@ import org.hibernate.type.Type; public abstract class AbstractParameterRegistrationImpl implements ParameterRegistrationImplementor { private static final Logger log = Logger.getLogger( AbstractParameterRegistrationImpl.class ); - private final CallImpl procedureCall; + private final ProcedureCallImpl procedureCall; private final Integer position; private final String name; @@ -63,7 +63,7 @@ public abstract class AbstractParameterRegistrationImpl implements ParameterR private int[] sqlTypes; protected AbstractParameterRegistrationImpl( - CallImpl procedureCall, + ProcedureCallImpl procedureCall, Integer position, Class type, ParameterMode mode) { @@ -71,7 +71,7 @@ public abstract class AbstractParameterRegistrationImpl implements ParameterR } protected AbstractParameterRegistrationImpl( - CallImpl procedureCall, + ProcedureCallImpl procedureCall, String name, Class type, ParameterMode mode) { @@ -79,7 +79,7 @@ public abstract class AbstractParameterRegistrationImpl implements ParameterR } private AbstractParameterRegistrationImpl( - CallImpl procedureCall, + ProcedureCallImpl procedureCall, Integer position, String name, Class type, @@ -96,7 +96,7 @@ public abstract class AbstractParameterRegistrationImpl implements ParameterR } protected SessionImplementor session() { - return procedureCall.session(); + return procedureCall.getSession(); } @Override @@ -258,7 +258,7 @@ public abstract class AbstractParameterRegistrationImpl implements ParameterR } } catch (SQLException e) { - throw procedureCall.session().getFactory().getSQLExceptionHelper().convert( + throw procedureCall.getSession().getFactory().getSQLExceptionHelper().convert( e, "Unable to extract OUT/INOUT parameter value" ); diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/NamedParameterRegistration.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/NamedParameterRegistration.java index 0df1623b8a..d3a772cb70 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/NamedParameterRegistration.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/NamedParameterRegistration.java @@ -30,7 +30,7 @@ import javax.persistence.ParameterMode; */ public class NamedParameterRegistration extends AbstractParameterRegistrationImpl { public NamedParameterRegistration( - CallImpl procedureCall, + ProcedureCallImpl procedureCall, String name, Class type, ParameterMode mode) { diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/PositionalParameterRegistration.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/PositionalParameterRegistration.java index b60235659c..a991525c58 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/PositionalParameterRegistration.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/PositionalParameterRegistration.java @@ -30,7 +30,7 @@ import javax.persistence.ParameterMode; */ public class PositionalParameterRegistration extends AbstractParameterRegistrationImpl { public PositionalParameterRegistration( - CallImpl procedureCall, + ProcedureCallImpl procedureCall, Integer position, Class type, ParameterMode mode) { diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/CallImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java similarity index 84% rename from hibernate-core/src/main/java/org/hibernate/procedure/internal/CallImpl.java rename to hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java index 15b6079303..0f82a10e6c 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/CallImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java @@ -28,7 +28,6 @@ import java.sql.CallableStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -48,18 +47,19 @@ import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.AbstractBasicQueryContractImpl; import org.hibernate.internal.util.StringHelper; import org.hibernate.persister.entity.EntityPersister; -import org.hibernate.procedure.Call; +import org.hibernate.procedure.ProcedureCall; import org.hibernate.procedure.NamedParametersNotSupportedException; import org.hibernate.procedure.ParameterRegistration; -import org.hibernate.procedure.Outputs; +import org.hibernate.procedure.ProcedureResult; +import org.hibernate.result.spi.ResultContext; import org.hibernate.type.Type; /** - * Standard implementation of {@link Call} + * Standard implementation of {@link org.hibernate.procedure.ProcedureCall} * * @author Steve Ebersole */ -public class CallImpl extends AbstractBasicQueryContractImpl implements Call { +public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements ProcedureCall, ResultContext { private final String procedureName; private final NativeSQLQueryReturn[] queryReturns; @@ -68,15 +68,15 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { private Set synchronizedQuerySpaces; - private OutputsImpl outputs; + private ProcedureResultImpl outputs; @SuppressWarnings("unchecked") - public CallImpl(SessionImplementor session, String procedureName) { + public ProcedureCallImpl(SessionImplementor session, String procedureName) { this( session, procedureName, (List) null ); } - public CallImpl(SessionImplementor session, String procedureName, List queryReturns) { + public ProcedureCallImpl(SessionImplementor session, String procedureName, List queryReturns) { super( session ); this.procedureName = procedureName; @@ -88,7 +88,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { } } - public CallImpl(SessionImplementor session, String procedureName, Class... resultClasses) { + public ProcedureCallImpl(SessionImplementor session, String procedureName, Class... resultClasses) { this( session, procedureName, collectQueryReturns( resultClasses ) ); } @@ -106,7 +106,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { return queryReturns; } - public CallImpl(SessionImplementor session, String procedureName, String... resultSetMappings) { + public ProcedureCallImpl(SessionImplementor session, String procedureName, String... resultSetMappings) { this( session, procedureName, collectQueryReturns( session, resultSetMappings ) ); } @@ -126,7 +126,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { return queryReturns; } -// public CallImpl( +// public ProcedureCallImpl( // SessionImplementor session, // String procedureName, // List parameters) { @@ -139,8 +139,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { // } @Override - public SessionImplementor session() { - // provide access to delegates + public SessionImplementor getSession() { return super.session(); } @@ -153,7 +152,13 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { return procedureName; } - NativeSQLQueryReturn[] getQueryReturns() { + @Override + public String getSql() { + return getProcedureName(); + } + + @Override + public NativeSQLQueryReturn[] getQueryReturns() { return queryReturns; } @@ -167,7 +172,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { @Override @SuppressWarnings("unchecked") - public Call registerParameter0(int position, Class type, ParameterMode mode) { + public ProcedureCall registerParameter0(int position, Class type, ParameterMode mode) { registerParameter( position, type, mode ); return this; } @@ -198,7 +203,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { } if ( parameterStrategy == null ) { // protect to only do this check once - final ExtractedDatabaseMetaData databaseMetaData = session().getTransactionCoordinator() + final ExtractedDatabaseMetaData databaseMetaData = getSession().getTransactionCoordinator() .getJdbcCoordinator() .getLogicalConnection() .getJdbcServices() @@ -235,7 +240,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { @Override @SuppressWarnings("unchecked") - public Call registerParameter0(String name, Class type, ParameterMode mode) { + public ProcedureCall registerParameter0(String name, Class type, ParameterMode mode) { registerParameter( name, type, mode ); return this; } @@ -260,7 +265,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { } @Override - public Outputs getOutputs() { + public ProcedureResult getResult() { if ( outputs == null ) { outputs = buildOutputs(); } @@ -268,7 +273,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { return outputs; } - private OutputsImpl buildOutputs() { + private ProcedureResultImpl buildOutputs() { // todo : going to need a very specialized Loader for this. // or, might be a good time to look at splitting Loader up into: // 1) building statement objects @@ -291,7 +296,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { buffer.append( ")}" ); try { - final CallableStatement statement = (CallableStatement) session().getTransactionCoordinator() + final CallableStatement statement = (CallableStatement) getSession().getTransactionCoordinator() .getJdbcCoordinator() .getStatementPreparer() .prepareStatement( buffer.toString(), true ); @@ -307,10 +312,10 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { i += parameter.getSqlTypes().length; } - return new OutputsImpl( this, statement ); + return new ProcedureResultImpl( this, statement ); } catch (SQLException e) { - throw session().getFactory().getSQLExceptionHelper().convert( + throw getSession().getFactory().getSQLExceptionHelper().convert( e, "Error preparing CallableStatement", getProcedureName() @@ -333,7 +338,7 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { @Override @SuppressWarnings("unchecked") - public Collection getSynchronizedQuerySpaces() { + public Set getSynchronizedQuerySpaces() { if ( synchronizedQuerySpaces == null ) { return Collections.emptySet(); } @@ -342,19 +347,15 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { } } - public Set getSynchronizedQuerySpacesSet() { - return (Set) getSynchronizedQuerySpaces(); - } - @Override - public CallImpl addSynchronizedQuerySpace(String querySpace) { + public ProcedureCallImpl addSynchronizedQuerySpace(String querySpace) { synchronizedQuerySpaces().add( querySpace ); return this; } @Override - public CallImpl addSynchronizedEntityName(String entityName) { - addSynchronizedQuerySpaces( session().getFactory().getEntityPersister( entityName ) ); + public ProcedureCallImpl addSynchronizedEntityName(String entityName) { + addSynchronizedQuerySpaces( getSession().getFactory().getEntityPersister( entityName ) ); return this; } @@ -363,11 +364,16 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call { } @Override - public CallImpl addSynchronizedEntityClass(Class entityClass) { - addSynchronizedQuerySpaces( session().getFactory().getEntityPersister( entityClass.getName() ) ); + public ProcedureCallImpl addSynchronizedEntityClass(Class entityClass) { + addSynchronizedQuerySpaces( getSession().getFactory().getEntityPersister( entityClass.getName() ) ); return this; } + @Override + public QueryParameters getQueryParameters() { + return buildQueryParametersObject(); + } + public QueryParameters buildQueryParametersObject() { QueryParameters qp = super.buildQueryParametersObject(); // both of these are for documentation purposes, they are actually handled directly... diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureResultImpl.java b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureResultImpl.java new file mode 100644 index 0000000000..6b52b3f895 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureResultImpl.java @@ -0,0 +1,116 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.procedure.internal; + +import java.sql.CallableStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.hibernate.JDBCException; +import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport; +import org.hibernate.procedure.ParameterRegistration; +import org.hibernate.procedure.ProcedureResult; +import org.hibernate.result.Return; +import org.hibernate.result.internal.ResultImpl; + +/** + * @author Steve Ebersole + */ +public class ProcedureResultImpl extends ResultImpl implements ProcedureResult { + private final ProcedureCallImpl procedureCall; + private final CallableStatement callableStatement; + + private final ParameterRegistrationImplementor[] refCursorParameters; + private int refCursorParamIndex = 0; + + ProcedureResultImpl(ProcedureCallImpl procedureCall, CallableStatement callableStatement) { + super( procedureCall, callableStatement ); + this.procedureCall = procedureCall; + this.callableStatement = callableStatement; + + this.refCursorParameters = procedureCall.collectRefCursorParameters(); + } + + @Override + public T getOutputParameterValue(ParameterRegistration parameterRegistration) { + return ( (ParameterRegistrationImplementor) parameterRegistration ).extract( callableStatement ); + } + + @Override + public Object getOutputParameterValue(String name) { + return procedureCall.getParameterRegistration( name ).extract( callableStatement ); + } + + @Override + public Object getOutputParameterValue(int position) { + return procedureCall.getParameterRegistration( position ).extract( callableStatement ); + } + + @Override + protected CurrentReturnDescriptor buildCurrentReturnDescriptor(boolean isResultSet, int updateCount) { + return new ProcedureCurrentReturnDescriptor( isResultSet, updateCount, refCursorParamIndex ); + } + + protected boolean hasMoreReturns(CurrentReturnDescriptor descriptor) { + return super.hasMoreReturns( descriptor ) + || ( (ProcedureCurrentReturnDescriptor) descriptor ).refCursorParamIndex < refCursorParameters.length; + } + + @Override + protected Return buildExtendedReturn(CurrentReturnDescriptor returnDescriptor) { + this.refCursorParamIndex++; + ResultSet resultSet; + int refCursorParamIndex = ( (ProcedureCurrentReturnDescriptor) returnDescriptor ).refCursorParamIndex; + ParameterRegistrationImplementor refCursorParam = refCursorParameters[refCursorParamIndex]; + if ( refCursorParam.getName() != null ) { + resultSet = procedureCall.getSession().getFactory().getServiceRegistry() + .getService( RefCursorSupport.class ) + .getResultSet( callableStatement, refCursorParam.getName() ); + } + else { + resultSet = procedureCall.getSession().getFactory().getServiceRegistry() + .getService( RefCursorSupport.class ) + .getResultSet( callableStatement, refCursorParam.getPosition() ); + } + return new ResultSetReturn( this, resultSet ); + } + + protected JDBCException convert(SQLException e, String message) { + return procedureCall.getSession().getFactory().getSQLExceptionHelper().convert( + e, + message, + procedureCall.getProcedureName() + ); + } + + protected static class ProcedureCurrentReturnDescriptor extends CurrentReturnDescriptor { + private final int refCursorParamIndex; + + private ProcedureCurrentReturnDescriptor(boolean isResultSet, int updateCount, int refCursorParamIndex) { + super( isResultSet, updateCount ); + this.refCursorParamIndex = refCursorParamIndex; + } + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/package-info.java b/hibernate-core/src/main/java/org/hibernate/procedure/package-info.java index 0339ee21f8..dea61abc24 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/package-info.java +++ b/hibernate-core/src/main/java/org/hibernate/procedure/package-info.java @@ -3,21 +3,21 @@ package org.hibernate.procedure; /** * Defines support for executing database stored procedures and functions and accessing its outputs. *

- * First a reference to {@link Call} is obtained through one of the overloaded - * {@link org.hibernate.Session#createStoredProcedureCall} methods. The Call reference is then used to "configure" + * First a reference to {@link ProcedureCall} is obtained through one of the overloaded + * {@link org.hibernate.Session#createStoredProcedureCall} methods. The ProcedureCall reference is then used to "configure" * the procedure call (set timeouts, etc) and to perform parameter registration. All procedure parameters that the * application wants to use must be registered. For all IN and INOUT parameters, values can then be bound. *

* At this point we are ready to execute the procedure call and start accessing the outputs. This is done by first - * calling the {@link Call#getOutputs()} method. The underlying JDBC call is executed as needed. The pattern to - * access the returns is iterating through the outputs while {@link Outputs#hasMoreReturns()} returns {@code true} and - * calling {@link Outputs#getNextReturn()} during iteration: + * calling the {@link ProcedureCall#getResult()} method. The underlying JDBC call is executed as needed. The pattern to + * access the returns is iterating through the outputs while {@link ProcedureResult#hasMoreReturns()} returns {@code true} and + * calling {@link ProcedureResult#getNextReturn()} during iteration: * - * Call call = session.createStoredProcedureCall( "some_procedure" ); + * ProcedureCall call = session.createStoredProcedureCall( "some_procedure" ); * ... - * Outputs = call.getOutputs(); - * while ( call.hasMoreReturns() ) { - * final Return rtn = call.getNextReturn(); + * ProcedureResult result = call.getResult(); + * while ( result.hasMoreReturns() ) { + * final Return rtn = result.getNextReturn(); * if ( rtn.isResultSet() ) { * handleResultSetReturn( (ResultSetReturn) rtn ); * } @@ -27,7 +27,7 @@ package org.hibernate.procedure; * } * *

- * Finally output parameters can be accessed using the overloaded {@link Outputs#getOutputParameterValue} methods. + * Finally output parameters can be accessed using the overloaded {@link ProcedureResult#getOutputParameterValue} methods. * For portability amongst databases, it is advised to access the output parameters after all returns have been * processed. * diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/InOutParameterRegistration.java b/hibernate-core/src/main/java/org/hibernate/result/NoMoreReturnsException.java similarity index 83% rename from hibernate-core/src/main/java/org/hibernate/procedure/InOutParameterRegistration.java rename to hibernate-core/src/main/java/org/hibernate/result/NoMoreReturnsException.java index 64ad751a76..728a4a3e4e 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/InOutParameterRegistration.java +++ b/hibernate-core/src/main/java/org/hibernate/result/NoMoreReturnsException.java @@ -21,10 +21,15 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.procedure; +package org.hibernate.result; + +import org.hibernate.HibernateException; /** * @author Steve Ebersole */ -public interface InOutParameterRegistration extends InParameterRegistration, OutParameterRegistration { +public class NoMoreReturnsException extends HibernateException { + public NoMoreReturnsException(String message) { + super( message ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/OutParameterRegistration.java b/hibernate-core/src/main/java/org/hibernate/result/Result.java similarity index 55% rename from hibernate-core/src/main/java/org/hibernate/procedure/OutParameterRegistration.java rename to hibernate-core/src/main/java/org/hibernate/result/Result.java index fb204dfb90..e42eeb8271 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/OutParameterRegistration.java +++ b/hibernate-core/src/main/java/org/hibernate/result/Result.java @@ -21,10 +21,30 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.procedure; +package org.hibernate.result; /** + * Represents the result of executing a JDBC statement accounting for mixing of result sets and update counts hiding the + * complexity (IMO) of how this is exposed in the JDBC API. + * + * A result is made up of group of {@link Return} objects, each representing a single result set or update count. + * Conceptually, Result presents those Returns as an iterator. + * * @author Steve Ebersole */ -public interface OutParameterRegistration extends ParameterRegistration { +public interface Result { + /** + * Are there any more returns associated with this result? + * + * @return {@code true} means there are more returns available via {@link #getNextReturn()}; {@code false} + * indicates that calling {@link #getNextReturn()} will certainly result in an exception. + */ + public boolean hasMoreReturns(); + + /** + * Retrieve the next return. + * + * @return The next return. + */ + public Return getNextReturn() throws NoMoreReturnsException; } diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/ResultSetReturn.java b/hibernate-core/src/main/java/org/hibernate/result/ResultSetReturn.java similarity index 94% rename from hibernate-core/src/main/java/org/hibernate/procedure/ResultSetReturn.java rename to hibernate-core/src/main/java/org/hibernate/result/ResultSetReturn.java index 20e8e5d3e4..9c520d8ada 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/ResultSetReturn.java +++ b/hibernate-core/src/main/java/org/hibernate/result/ResultSetReturn.java @@ -21,12 +21,12 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.procedure; +package org.hibernate.result; import java.util.List; /** - * Models a stored procedure result that is a result set. + * Models a return that is a result set. * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/Return.java b/hibernate-core/src/main/java/org/hibernate/result/Return.java similarity index 91% rename from hibernate-core/src/main/java/org/hibernate/procedure/Return.java rename to hibernate-core/src/main/java/org/hibernate/result/Return.java index 6295617f2d..93c75356ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/Return.java +++ b/hibernate-core/src/main/java/org/hibernate/result/Return.java @@ -21,10 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.procedure; +package org.hibernate.result; /** - * Common contract for procedure call results which can be either results ({@link ResultSetReturn}) or update + * Common contract for individual return objects which can be either results ({@link ResultSetReturn}) or update * counts ({@link UpdateCountReturn}). * * @author Steve Ebersole diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/UpdateCountReturn.java b/hibernate-core/src/main/java/org/hibernate/result/UpdateCountReturn.java similarity index 92% rename from hibernate-core/src/main/java/org/hibernate/procedure/UpdateCountReturn.java rename to hibernate-core/src/main/java/org/hibernate/result/UpdateCountReturn.java index a837b78537..5574b3f70f 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/UpdateCountReturn.java +++ b/hibernate-core/src/main/java/org/hibernate/result/UpdateCountReturn.java @@ -21,10 +21,10 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.procedure; +package org.hibernate.result; /** - * Models a stored procedure result that is a result set. + * Models a return that is an update count (count of rows affected) * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/internal/OutputsImpl.java b/hibernate-core/src/main/java/org/hibernate/result/internal/ResultImpl.java similarity index 59% rename from hibernate-core/src/main/java/org/hibernate/procedure/internal/OutputsImpl.java rename to hibernate-core/src/main/java/org/hibernate/result/internal/ResultImpl.java index cd68b1efcc..fe405ec56f 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/internal/OutputsImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/result/internal/ResultImpl.java @@ -1,7 +1,7 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * Copyright (c) 2013, Red Hat Inc. or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Inc. @@ -21,9 +21,9 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.procedure.internal; +package org.hibernate.result.internal; -import java.sql.CallableStatement; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collections; @@ -32,53 +32,34 @@ import java.util.Map; import java.util.Set; import org.hibernate.JDBCException; -import org.hibernate.procedure.Outputs; -import org.hibernate.procedure.ParameterRegistration; -import org.hibernate.procedure.Return; import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.loader.custom.CustomLoader; import org.hibernate.loader.custom.CustomQuery; import org.hibernate.loader.custom.sql.SQLQueryReturnProcessor; -import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport; +import org.hibernate.result.NoMoreReturnsException; +import org.hibernate.result.Result; +import org.hibernate.result.Return; +import org.hibernate.result.spi.ResultContext; /** * @author Steve Ebersole */ -public class OutputsImpl implements Outputs { - private final CallImpl procedureCall; - private final CallableStatement callableStatement; - - private final ParameterRegistrationImplementor[] refCursorParameters; +public class ResultImpl implements Result { + private final ResultContext context; + private final PreparedStatement jdbcStatement; private final CustomLoaderExtension loader; private CurrentReturnDescriptor currentReturnDescriptor; private boolean executed = false; - private int refCursorParamIndex = 0; - OutputsImpl(CallImpl procedureCall, CallableStatement callableStatement) { - this.procedureCall = procedureCall; - this.callableStatement = callableStatement; + public ResultImpl(ResultContext context, PreparedStatement jdbcStatement) { + this.context = context; + this.jdbcStatement = jdbcStatement; - this.refCursorParameters = procedureCall.collectRefCursorParameters(); // For now... - this.loader = buildSpecializedCustomLoader( procedureCall ); - } - - @Override - public T getOutputParameterValue(ParameterRegistration parameterRegistration) { - return ( (ParameterRegistrationImplementor) parameterRegistration ).extract( callableStatement ); - } - - @Override - public Object getOutputParameterValue(String name) { - return procedureCall.getParameterRegistration( name ).extract( callableStatement ); - } - - @Override - public Object getOutputParameterValue(int position) { - return procedureCall.getParameterRegistration( position ).extract( callableStatement ); + this.loader = buildSpecializedCustomLoader( context ); } @Override @@ -88,7 +69,7 @@ public class OutputsImpl implements Outputs { if ( executed ) { try { - isResultSet = callableStatement.getMoreResults(); + isResultSet = jdbcStatement.getMoreResults(); } catch (SQLException e) { throw convert( e, "Error calling CallableStatement.getMoreResults" ); @@ -96,7 +77,7 @@ public class OutputsImpl implements Outputs { } else { try { - isResultSet = callableStatement.execute(); + isResultSet = jdbcStatement.execute(); } catch (SQLException e) { throw convert( e, "Error calling CallableStatement.execute" ); @@ -107,23 +88,26 @@ public class OutputsImpl implements Outputs { int updateCount = -1; if ( ! isResultSet ) { try { - updateCount = callableStatement.getUpdateCount(); + updateCount = jdbcStatement.getUpdateCount(); } catch (SQLException e) { throw convert( e, "Error calling CallableStatement.getUpdateCount" ); } } - currentReturnDescriptor = new CurrentReturnDescriptor( isResultSet, updateCount, refCursorParamIndex ); + currentReturnDescriptor = buildCurrentReturnDescriptor( isResultSet, updateCount ); } - return hasMoreResults( currentReturnDescriptor ); + return hasMoreReturns( currentReturnDescriptor ); } - private boolean hasMoreResults(CurrentReturnDescriptor descriptor) { + protected CurrentReturnDescriptor buildCurrentReturnDescriptor(boolean isResultSet, int updateCount) { + return new CurrentReturnDescriptor( isResultSet, updateCount ); + } + + protected boolean hasMoreReturns(CurrentReturnDescriptor descriptor) { return descriptor.isResultSet - || descriptor.updateCount >= 0 - || descriptor.refCursorParamIndex < refCursorParameters.length; + || descriptor.updateCount >= 0; } @Override @@ -137,8 +121,8 @@ public class OutputsImpl implements Outputs { } } - if ( ! hasMoreResults( currentReturnDescriptor ) ) { - throw new IllegalStateException( "Results have been exhausted" ); + if ( ! hasMoreReturns( currentReturnDescriptor ) ) { + throw new NoMoreReturnsException( "Results have been exhausted" ); } CurrentReturnDescriptor copyReturnDescriptor = currentReturnDescriptor; @@ -146,7 +130,7 @@ public class OutputsImpl implements Outputs { if ( copyReturnDescriptor.isResultSet ) { try { - return new ResultSetReturn( this, callableStatement.getResultSet() ); + return new ResultSetReturn( this, jdbcStatement.getResultSet() ); } catch (SQLException e) { throw convert( e, "Error calling CallableStatement.getResultSet" ); @@ -156,49 +140,37 @@ public class OutputsImpl implements Outputs { return new UpdateCountReturn( this, copyReturnDescriptor.updateCount ); } else { - this.refCursorParamIndex++; - ResultSet resultSet; - int refCursorParamIndex = copyReturnDescriptor.refCursorParamIndex; - ParameterRegistrationImplementor refCursorParam = refCursorParameters[refCursorParamIndex]; - if ( refCursorParam.getName() != null ) { - resultSet = procedureCall.session().getFactory().getServiceRegistry() - .getService( RefCursorSupport.class ) - .getResultSet( callableStatement, refCursorParam.getName() ); - } - else { - resultSet = procedureCall.session().getFactory().getServiceRegistry() - .getService( RefCursorSupport.class ) - .getResultSet( callableStatement, refCursorParam.getPosition() ); - } - return new ResultSetReturn( this, resultSet ); + return buildExtendedReturn( copyReturnDescriptor ); } } + protected Return buildExtendedReturn(CurrentReturnDescriptor copyReturnDescriptor) { + throw new NoMoreReturnsException( "Results have been exhausted" ); + } + protected JDBCException convert(SQLException e, String message) { - return procedureCall.session().getFactory().getSQLExceptionHelper().convert( + return context.getSession().getFactory().getSQLExceptionHelper().convert( e, message, - procedureCall.getProcedureName() + context.getSql() ); } - private static class CurrentReturnDescriptor { + protected static class CurrentReturnDescriptor { private final boolean isResultSet; private final int updateCount; - private final int refCursorParamIndex; - private CurrentReturnDescriptor(boolean isResultSet, int updateCount, int refCursorParamIndex) { + protected CurrentReturnDescriptor(boolean isResultSet, int updateCount) { this.isResultSet = isResultSet; this.updateCount = updateCount; - this.refCursorParamIndex = refCursorParamIndex; } } - private static class ResultSetReturn implements org.hibernate.procedure.ResultSetReturn { - private final OutputsImpl storedProcedureOutputs; + protected static class ResultSetReturn implements org.hibernate.result.ResultSetReturn { + private final ResultImpl storedProcedureOutputs; private final ResultSet resultSet; - public ResultSetReturn(OutputsImpl storedProcedureOutputs, ResultSet resultSet) { + public ResultSetReturn(ResultImpl storedProcedureOutputs, ResultSet resultSet) { this.storedProcedureOutputs = storedProcedureOutputs; this.resultSet = resultSet; } @@ -231,12 +203,12 @@ public class OutputsImpl implements Outputs { } } - private class UpdateCountReturn implements org.hibernate.procedure.UpdateCountReturn { - private final OutputsImpl procedureOutputs; + protected static class UpdateCountReturn implements org.hibernate.result.UpdateCountReturn { + private final ResultImpl result; private final int updateCount; - public UpdateCountReturn(OutputsImpl procedureOutputs, int updateCount) { - this.procedureOutputs = procedureOutputs; + public UpdateCountReturn(ResultImpl result, int updateCount) { + this.result = result; this.updateCount = updateCount; } @@ -251,10 +223,10 @@ public class OutputsImpl implements Outputs { } } - private static CustomLoaderExtension buildSpecializedCustomLoader(final CallImpl procedureCall) { + private static CustomLoaderExtension buildSpecializedCustomLoader(final ResultContext context) { final SQLQueryReturnProcessor processor = new SQLQueryReturnProcessor( - procedureCall.getQueryReturns(), - procedureCall.session().getFactory() + context.getQueryReturns(), + context.getSession().getFactory() ); processor.process(); final List customReturns = processor.generateCustomReturns( false ); @@ -262,12 +234,12 @@ public class OutputsImpl implements Outputs { CustomQuery customQuery = new CustomQuery() { @Override public String getSQL() { - return procedureCall.getProcedureName(); + return context.getSql(); } @Override public Set getQuerySpaces() { - return procedureCall.getSynchronizedQuerySpacesSet(); + return context.getSynchronizedQuerySpaces(); } @Override @@ -284,8 +256,8 @@ public class OutputsImpl implements Outputs { return new CustomLoaderExtension( customQuery, - procedureCall.buildQueryParametersObject(), - procedureCall.session() + context.getQueryParameters(), + context.getSession() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/result/package-info.java b/hibernate-core/src/main/java/org/hibernate/result/package-info.java new file mode 100644 index 0000000000..8aa9877fa3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/result/package-info.java @@ -0,0 +1,24 @@ +package org.hibernate.result; + +/** + * Defines support for dealing with database results, accounting for mixed result sets and update counts hiding the + * complexity (IMO) of how this is exposed in the JDBC API. + * + * {@link Result} represents the overall group of results. + * + * {@link Return} represents the mixed individual outcomes, which might be either a {@link ResultSetReturn} or + * a {@link UpdateCountReturn}. + * + * + * Result result = ...; + * while ( result.hasMoreReturns() ) { + * final Return rtn = result.getNextReturn(); + * if ( rtn.isResultSet() ) { + * handleResultSetReturn( (ResultSetReturn) rtn ); + * } + * else { + * handleUpdateCountReturn( (UpdateCountReturn) rtn ); + * } + * } + * + */ \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/procedure/InParameterRegistration.java b/hibernate-core/src/main/java/org/hibernate/result/spi/ResultContext.java similarity index 67% rename from hibernate-core/src/main/java/org/hibernate/procedure/InParameterRegistration.java rename to hibernate-core/src/main/java/org/hibernate/result/spi/ResultContext.java index d7f6fca934..60a2600c76 100644 --- a/hibernate-core/src/main/java/org/hibernate/procedure/InParameterRegistration.java +++ b/hibernate-core/src/main/java/org/hibernate/result/spi/ResultContext.java @@ -21,10 +21,24 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.procedure; +package org.hibernate.result.spi; + +import java.util.Set; + +import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn; +import org.hibernate.engine.spi.QueryParameters; +import org.hibernate.engine.spi.SessionImplementor; /** * @author Steve Ebersole */ -public interface InParameterRegistration extends ParameterRegistration { +public interface ResultContext { + public SessionImplementor getSession(); + public Set getSynchronizedQuerySpaces(); + + // for now... + // see Loader-redesign proposal + public String getSql(); + public QueryParameters getQueryParameters(); + public NativeSQLQueryReturn[] getQueryReturns(); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureTest.java b/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureTest.java index 2ac5d85efc..eb664c5223 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/sql/storedproc/StoredProcedureTest.java @@ -32,10 +32,10 @@ import org.hibernate.cfg.Configuration; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.Mapping; import org.hibernate.mapping.AuxiliaryDatabaseObject; -import org.hibernate.procedure.Call; -import org.hibernate.procedure.Outputs; -import org.hibernate.procedure.ResultSetReturn; -import org.hibernate.procedure.Return; +import org.hibernate.procedure.ProcedureCall; +import org.hibernate.procedure.ProcedureResult; +import org.hibernate.result.ResultSetReturn; +import org.hibernate.result.Return; import org.hibernate.dialect.H2Dialect; import org.junit.Test; @@ -169,10 +169,10 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase { Session session = openSession(); session.beginTransaction(); - Call query = session.createStoredProcedureCall( "user"); - Outputs outputs = query.getOutputs(); - assertTrue( "Checking Outputs has more returns", outputs.hasMoreReturns() ); - Return nextReturn = outputs.getNextReturn(); + ProcedureCall query = session.createStoredProcedureCall( "user"); + ProcedureResult procedureResult = query.getResult(); + assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() ); + Return nextReturn = procedureResult.getNextReturn(); assertNotNull( nextReturn ); ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() ); ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn; @@ -188,10 +188,10 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase { Session session = openSession(); session.beginTransaction(); - Call query = session.createStoredProcedureCall( "findOneUser" ); - Outputs outputs = query.getOutputs(); - assertTrue( "Checking Outputs has more returns", outputs.hasMoreReturns() ); - Return nextReturn = outputs.getNextReturn(); + ProcedureCall query = session.createStoredProcedureCall( "findOneUser" ); + ProcedureResult procedureResult = query.getResult(); + assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() ); + Return nextReturn = procedureResult.getNextReturn(); assertNotNull( nextReturn ); ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() ); ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn; @@ -209,10 +209,10 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase { Session session = openSession(); session.beginTransaction(); - Call query = session.createStoredProcedureCall( "findUsers" ); - Outputs outputs = query.getOutputs(); - assertTrue( "Checking Outputs has more returns", outputs.hasMoreReturns() ); - Return nextReturn = outputs.getNextReturn(); + ProcedureCall query = session.createStoredProcedureCall( "findUsers" ); + ProcedureResult procedureResult = query.getResult(); + assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() ); + Return nextReturn = procedureResult.getNextReturn(); assertNotNull( nextReturn ); ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() ); ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn; @@ -246,12 +246,12 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase { Session session = openSession(); session.beginTransaction(); - Call query = session.createStoredProcedureCall( "findUserRange" ); + ProcedureCall query = session.createStoredProcedureCall( "findUserRange" ); query.registerParameter( "start", Integer.class, ParameterMode.IN ).bindValue( 1 ); query.registerParameter( "end", Integer.class, ParameterMode.IN ).bindValue( 2 ); - Outputs outputs = query.getOutputs(); - assertTrue( "Checking Outputs has more returns", outputs.hasMoreReturns() ); - Return nextReturn = outputs.getNextReturn(); + ProcedureResult procedureResult = query.getResult(); + assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() ); + Return nextReturn = procedureResult.getNextReturn(); assertNotNull( nextReturn ); ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() ); ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn; @@ -273,12 +273,12 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase { Session session = openSession(); session.beginTransaction(); - Call query = session.createStoredProcedureCall( "findUserRange" ); + ProcedureCall query = session.createStoredProcedureCall( "findUserRange" ); query.registerParameter( 1, Integer.class, ParameterMode.IN ).bindValue( 1 ); query.registerParameter( 2, Integer.class, ParameterMode.IN ).bindValue( 2 ); - Outputs outputs = query.getOutputs(); - assertTrue( "Checking Outputs has more returns", outputs.hasMoreReturns() ); - Return nextReturn = outputs.getNextReturn(); + ProcedureResult procedureResult = query.getResult(); + assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() ); + Return nextReturn = procedureResult.getNextReturn(); assertNotNull( nextReturn ); ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() ); ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn; @@ -304,12 +304,12 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase { // execution { - Call query = session.createStoredProcedureCall( "findUserRange" ); + ProcedureCall query = session.createStoredProcedureCall( "findUserRange" ); query.registerParameter( 1, Integer.class, ParameterMode.IN ); query.registerParameter( 2, Integer.class, ParameterMode.IN ).bindValue( 2 ); - Outputs outputs = query.getOutputs(); + ProcedureResult procedureResult = query.getResult(); try { - outputs.hasMoreReturns(); + procedureResult.hasMoreReturns(); fail( "Expecting failure due to missing parameter bind" ); } catch (JDBCException expected) { @@ -317,12 +317,12 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase { } { - Call query = session.createStoredProcedureCall( "findUserRange" ); + ProcedureCall query = session.createStoredProcedureCall( "findUserRange" ); query.registerParameter( "start", Integer.class, ParameterMode.IN ); query.registerParameter( "end", Integer.class, ParameterMode.IN ).bindValue( 2 ); - Outputs outputs = query.getOutputs(); + ProcedureResult procedureResult = query.getResult(); try { - outputs.hasMoreReturns(); + procedureResult.hasMoreReturns(); fail( "Expecting failure due to missing parameter bind" ); } catch (JDBCException expected) { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java index e550395d22..7c4fecffd1 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/StoredProcedureQueryImpl.java @@ -37,11 +37,11 @@ import java.util.List; import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.LockMode; -import org.hibernate.procedure.Call; -import org.hibernate.procedure.Outputs; -import org.hibernate.procedure.ResultSetReturn; -import org.hibernate.procedure.Return; -import org.hibernate.procedure.UpdateCountReturn; +import org.hibernate.procedure.ProcedureCall; +import org.hibernate.procedure.ProcedureResult; +import org.hibernate.result.ResultSetReturn; +import org.hibernate.result.Return; +import org.hibernate.result.UpdateCountReturn; import org.hibernate.jpa.spi.BaseQueryImpl; import org.hibernate.jpa.spi.HibernateEntityManagerImplementor; @@ -49,10 +49,10 @@ import org.hibernate.jpa.spi.HibernateEntityManagerImplementor; * @author Steve Ebersole */ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredProcedureQuery { - private final Call procedureCall; - private Outputs procedureOutputs; + private final ProcedureCall procedureCall; + private ProcedureResult procedureResult; - public StoredProcedureQueryImpl(Call procedureCall, HibernateEntityManagerImplementor entityManager) { + public StoredProcedureQueryImpl(ProcedureCall procedureCall, HibernateEntityManagerImplementor entityManager) { super( entityManager ); this.procedureCall = procedureCall; } @@ -172,11 +172,11 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro // outputs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - private Outputs outputs() { - if ( procedureOutputs == null ) { - procedureOutputs = procedureCall.getOutputs(); + private ProcedureResult outputs() { + if ( procedureResult == null ) { + procedureResult = procedureCall.getResult(); } - return procedureOutputs; + return procedureResult; } @Override diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java index 60b7f1f386..19741179c2 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/spi/AbstractEntityManagerImpl.java @@ -83,7 +83,7 @@ import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.StaleObjectStateException; import org.hibernate.StaleStateException; -import org.hibernate.procedure.Call; +import org.hibernate.procedure.ProcedureCall; import org.hibernate.TransientObjectException; import org.hibernate.TypeMismatchException; import org.hibernate.UnresolvableObjectException; @@ -813,8 +813,8 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage @Override public StoredProcedureQuery createStoredProcedureQuery(String procedureName) { try { - Call call = getSession().createStoredProcedureCall( procedureName ); - return new StoredProcedureQueryImpl( call, this ); + ProcedureCall procedureCall = getSession().createStoredProcedureCall( procedureName ); + return new StoredProcedureQueryImpl( procedureCall, this ); } catch ( HibernateException he ) { throw convert( he ); @@ -824,8 +824,8 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage @Override public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) { try { - Call call = getSession().createStoredProcedureCall( procedureName, resultClasses ); - return new StoredProcedureQueryImpl( call, this ); + ProcedureCall procedureCall = getSession().createStoredProcedureCall( procedureName, resultClasses ); + return new StoredProcedureQueryImpl( procedureCall, this ); } catch ( HibernateException he ) { throw convert( he );