HHH-7914 - Improve new stored procedure call support

This commit is contained in:
Steve Ebersole 2013-01-14 14:24:45 -06:00
parent 9ce5c32dd7
commit 6062eb67ea
22 changed files with 380 additions and 237 deletions

View File

@ -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)

View File

@ -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 {

View File

@ -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 );

View File

@ -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();
}

View File

@ -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.
* <p/>
@ -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> T getOutputParameterValue(ParameterRegistration<T> 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();
}

View File

@ -48,7 +48,7 @@ import org.hibernate.type.Type;
public abstract class AbstractParameterRegistrationImpl<T> implements ParameterRegistrationImplementor<T> {
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<T> implements ParameterR
private int[] sqlTypes;
protected AbstractParameterRegistrationImpl(
CallImpl procedureCall,
ProcedureCallImpl procedureCall,
Integer position,
Class<T> type,
ParameterMode mode) {
@ -71,7 +71,7 @@ public abstract class AbstractParameterRegistrationImpl<T> implements ParameterR
}
protected AbstractParameterRegistrationImpl(
CallImpl procedureCall,
ProcedureCallImpl procedureCall,
String name,
Class<T> type,
ParameterMode mode) {
@ -79,7 +79,7 @@ public abstract class AbstractParameterRegistrationImpl<T> implements ParameterR
}
private AbstractParameterRegistrationImpl(
CallImpl procedureCall,
ProcedureCallImpl procedureCall,
Integer position,
String name,
Class<T> type,
@ -96,7 +96,7 @@ public abstract class AbstractParameterRegistrationImpl<T> implements ParameterR
}
protected SessionImplementor session() {
return procedureCall.session();
return procedureCall.getSession();
}
@Override
@ -258,7 +258,7 @@ public abstract class AbstractParameterRegistrationImpl<T> 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"
);

View File

@ -30,7 +30,7 @@ import javax.persistence.ParameterMode;
*/
public class NamedParameterRegistration<T> extends AbstractParameterRegistrationImpl<T> {
public NamedParameterRegistration(
CallImpl procedureCall,
ProcedureCallImpl procedureCall,
String name,
Class<T> type,
ParameterMode mode) {

View File

@ -30,7 +30,7 @@ import javax.persistence.ParameterMode;
*/
public class PositionalParameterRegistration<T> extends AbstractParameterRegistrationImpl<T> {
public PositionalParameterRegistration(
CallImpl procedureCall,
ProcedureCallImpl procedureCall,
Integer position,
Class<T> type,
ParameterMode mode) {

View File

@ -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<String> 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<NativeSQLQueryReturn> queryReturns) {
public ProcedureCallImpl(SessionImplementor session, String procedureName, List<NativeSQLQueryReturn> 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<StoredProcedureParameter> 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<String> getSynchronizedQuerySpaces() {
public Set<String> getSynchronizedQuerySpaces() {
if ( synchronizedQuerySpaces == null ) {
return Collections.emptySet();
}
@ -342,19 +347,15 @@ public class CallImpl extends AbstractBasicQueryContractImpl implements Call {
}
}
public Set<String> getSynchronizedQuerySpacesSet() {
return (Set<String>) 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...

View File

@ -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> T getOutputParameterValue(ParameterRegistration<T> parameterRegistration) {
return ( (ParameterRegistrationImplementor<T>) 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;
}
}
}

View File

@ -3,21 +3,21 @@ package org.hibernate.procedure;
/**
* Defines support for executing database stored procedures and functions and accessing its outputs.
* <p/>
* 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.
* <p/>
* 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:
* <code>
* 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;
* }
* </code>
* <p/>
* 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.
*

View File

@ -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<T> extends InParameterRegistration<T>, OutParameterRegistration<T> {
public class NoMoreReturnsException extends HibernateException {
public NoMoreReturnsException(String message) {
super( message );
}
}

View File

@ -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<T> extends ParameterRegistration<T> {
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;
}

View File

@ -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
*/

View File

@ -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

View File

@ -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
*/

View File

@ -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> T getOutputParameterValue(ParameterRegistration<T> parameterRegistration) {
return ( (ParameterRegistrationImplementor<T>) 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() );
return buildExtendedReturn( copyReturnDescriptor );
}
else {
resultSet = procedureCall.session().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.getResultSet( callableStatement, refCursorParam.getPosition() );
}
return new ResultSetReturn( this, resultSet );
}
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<org.hibernate.loader.custom.Return> 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<String> 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()
);
}

View File

@ -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}.
*
* <code>
* Result result = ...;
* while ( result.hasMoreReturns() ) {
* final Return rtn = result.getNextReturn();
* if ( rtn.isResultSet() ) {
* handleResultSetReturn( (ResultSetReturn) rtn );
* }
* else {
* handleUpdateCountReturn( (UpdateCountReturn) rtn );
* }
* }
* </code>
*/

View File

@ -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<T> extends ParameterRegistration<T> {
public interface ResultContext {
public SessionImplementor getSession();
public Set<String> getSynchronizedQuerySpaces();
// for now...
// see Loader-redesign proposal
public String getSql();
public QueryParameters getQueryParameters();
public NativeSQLQueryReturn[] getQueryReturns();
}

View File

@ -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) {

View File

@ -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

View File

@ -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 );