binding = getQueryParameterBindings().getBinding(
getParameterMetadata().getQueryParameter( position )
);
binding.setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(QueryParameter
parameter, P value) {
getQueryParameterBindings().getBinding( (QueryParameter) parameter ).setBindValue( value );
return this;
}
@SuppressWarnings("unchecked")
private
QueryParameterBinding
locateBinding(Parameter
parameter) {
if ( parameter instanceof QueryParameter ) {
return getQueryParameterBindings().getBinding( (QueryParameter) parameter );
}
else if ( parameter.getName() != null ) {
return getQueryParameterBindings().getBinding( parameter.getName() );
}
else if ( parameter.getPosition() != null ) {
return getQueryParameterBindings().getBinding( parameter.getPosition() );
}
throw getExceptionConverter().convert(
new IllegalArgumentException( "Could not resolve binding for given parameter reference [" + parameter + "]" )
);
}
private
QueryParameterBinding
locateBinding(String name) {
return getQueryParameterBindings().getBinding( name );
}
private
QueryParameterBinding
locateBinding(int position) {
return getQueryParameterBindings().getBinding( position );
}
@Override
@SuppressWarnings("unchecked")
public
QueryImplementor setParameter(Parameter
parameter, P value) {
getProducer().checkOpen();
if ( value instanceof TypedParameterValue ) {
setParameter( parameter, ( (TypedParameterValue) value ).getValue(), ( (TypedParameterValue) value ).getType() );
}
else if ( value instanceof Collection && !isRegisteredAsBasicType( value.getClass() ) ) {
locateListBinding( parameter ).setBindValues( (Collection) value );
}
else {
locateBinding( parameter ).setBindValue( value );
}
return this;
}
@SuppressWarnings("unchecked")
private
void setParameter(Parameter
parameter, Object value, Type type) {
if ( parameter instanceof QueryParameter ) {
setParameter( (QueryParameter) parameter, value, type );
}
else if ( value == null ) {
locateBinding( parameter ).setBindValue( null, type );
}
else if ( value instanceof Collection && !isRegisteredAsBasicType( value.getClass() ) ) {
locateListBinding( parameter ).setBindValues( (Collection) value, type );
}
else {
locateBinding( parameter ).setBindValue( (P) value, type );
}
}
private QueryParameterListBinding locateListBinding(Parameter parameter) {
if ( parameter instanceof QueryParameter ) {
return getQueryParameterBindings().getQueryParameterListBinding( (QueryParameter) parameter );
}
else {
return getQueryParameterBindings().getQueryParameterListBinding( parameter.getName() );
}
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(String name, Object value) {
getProducer().checkOpen();
if ( value instanceof TypedParameterValue ) {
final TypedParameterValue typedValueWrapper = (TypedParameterValue) value;
setParameter( name, typedValueWrapper.getValue(), typedValueWrapper.getType() );
}
else if ( value instanceof Collection && !isRegisteredAsBasicType( value.getClass() ) ) {
setParameterList( name, (Collection) value );
}
else {
getQueryParameterBindings().getBinding( name ).setBindValue( value );
}
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(int position, Object value) {
getProducer().checkOpen();
if ( value instanceof TypedParameterValue ) {
final TypedParameterValue typedParameterValue = (TypedParameterValue) value;
setParameter( position, typedParameterValue.getValue(), typedParameterValue.getType() );
}
else if ( value instanceof Collection && !isRegisteredAsBasicType( value.getClass() ) ) {
setParameterList( getParameterMetadata().getQueryParameter( position ), (Collection) value );
}
else {
getQueryParameterBindings().getBinding( position ).setBindValue( value );
}
return this;
}
@Override
@SuppressWarnings("unchecked")
public
QueryImplementor setParameter(QueryParameter
parameter, P value, Type type) {
getQueryParameterBindings().getBinding( parameter ).setBindValue( value, type );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(String name, Object value, Type type) {
getQueryParameterBindings().getBinding( name ).setBindValue( value, type );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(int position, Object value, Type type) {
getQueryParameterBindings().getBinding( position ).setBindValue( value, type );
return this;
}
@Override
@SuppressWarnings("unchecked")
public
QueryImplementor setParameter(QueryParameter
parameter, P value, TemporalType temporalType) {
getQueryParameterBindings().getBinding( parameter ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(String name, Object value, TemporalType temporalType) {
getQueryParameterBindings().getBinding( name ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(int position, Object value, TemporalType temporalType) {
getQueryParameterBindings().getBinding( position ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public
QueryImplementor setParameterList(QueryParameter parameter, Collection
values) {
getQueryParameterBindings().getQueryParameterListBinding( parameter ).setBindValues( values );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameterList(String name, Collection values) {
getQueryParameterBindings().getQueryParameterListBinding( name ).setBindValues( values );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameterList(int position, Collection values) {
getQueryParameterBindings().getQueryParameterListBinding( position ).setBindValues( values );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameterList(String name, Collection values, Type type) {
getQueryParameterBindings().getQueryParameterListBinding( name ).setBindValues( values, type );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameterList(int position, Collection values, Type type) {
getQueryParameterBindings().getQueryParameterListBinding( position ).setBindValues( values, type );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameterList(String name, Object[] values, Type type) {
getQueryParameterBindings().getQueryParameterListBinding( name ).setBindValues( Arrays.asList( values ), type );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameterList(int position, Object[] values, Type type) {
getQueryParameterBindings().getQueryParameterListBinding( position ).setBindValues( Arrays.asList( values ), type );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameterList(String name, Object[] values) {
getQueryParameterBindings().getQueryParameterListBinding( name ).setBindValues( Arrays.asList( values ) );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameterList(int position, Object[] values) {
getQueryParameterBindings().getQueryParameterListBinding( position ).setBindValues( Arrays.asList( values ) );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(Parameter param, Calendar value, TemporalType temporalType) {
getProducer().checkOpen();
getQueryParameterBindings().getBinding( (QueryParameter) param ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(Parameter param, Date value, TemporalType temporalType) {
getProducer().checkOpen();
getQueryParameterBindings().getBinding( (QueryParameter) param ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(String name, Calendar value, TemporalType temporalType) {
getProducer().checkOpen();
getQueryParameterBindings().getBinding( name ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(String name, Date value, TemporalType temporalType) {
getProducer().checkOpen();
getQueryParameterBindings().getBinding( name ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(int position, Calendar value, TemporalType temporalType) {
getProducer().checkOpen();
getQueryParameterBindings().getBinding( position ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setParameter(int position, Date value, TemporalType temporalType) {
getProducer().checkOpen();
getQueryParameterBindings().getBinding( position ).setBindValue( value, temporalType );
return this;
}
@Override
public Set> getParameters() {
getProducer().checkOpen( false );
return getParameterMetadata().collectAllParametersJpa();
}
@Override
public QueryParameter> getParameter(String name) {
getProducer().checkOpen( false );
try {
return getParameterMetadata().getQueryParameter( name );
}
catch ( HibernateException e ) {
throw getExceptionConverter().convert( e );
}
}
@Override
@SuppressWarnings("unchecked")
public QueryParameter getParameter(String name, Class type) {
getProducer().checkOpen( false );
try {
final QueryParameter parameter = getParameterMetadata().getQueryParameter( name );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
throw new IllegalArgumentException(
"The type [" + parameter.getParameterType().getName() +
"] associated with the parameter corresponding to name [" + name +
"] is not assignable to requested Java type [" + type.getName() + "]"
);
}
return parameter;
}
catch ( HibernateException e ) {
throw getExceptionConverter().convert( e );
}
}
@Override
public QueryParameter> getParameter(int position) {
getProducer().checkOpen( false );
try {
if ( getParameterMetadata().getPositionalParameterCount() == 0 ) {
try {
return getParameterMetadata().getQueryParameter( Integer.toString( position ) );
}
catch (HibernateException e) {
throw new QueryParameterException( "could not locate parameter at position [" + position + "]" );
}
}
// fallback to ordinal lookup
return getParameterMetadata().getQueryParameter( position );
}
catch (HibernateException e) {
throw getExceptionConverter().convert( e );
}
}
@Override
@SuppressWarnings("unchecked")
public QueryParameter getParameter(int position, Class type) {
getProducer().checkOpen( false );
try {
final QueryParameter parameter = getParameterMetadata().getQueryParameter( position );
if ( !parameter.getParameterType().isAssignableFrom( type ) ) {
throw new IllegalArgumentException(
"The type [" + parameter.getParameterType().getName() +
"] associated with the parameter corresponding to position [" + position +
"] is not assignable to requested Java type [" + type.getName() + "]"
);
}
return parameter;
}
catch ( HibernateException e ) {
throw getExceptionConverter().convert( e );
}
}
@Override
public boolean isBound(Parameter> parameter) {
getProducer().checkOpen();
return getQueryParameterBindings().isBound( (QueryParameter) parameter );
}
@Override
public T getParameterValue(Parameter parameter) {
LOGGER.tracef( "#getParameterValue(%s)", parameter );
getProducer().checkOpen( false );
return (T) getParameterValue(
(QueryParameter) parameter,
(queryParameter) -> new IllegalStateException( "Parameter value not yet bound : " + queryParameter.toString() ),
(queryParameter, e) -> {
final String message = "Parameter reference [" + queryParameter + "] did not come from this query";
if ( e == null ) {
return new IllegalArgumentException( message );
}
return new IllegalArgumentException( message, e );
},
(queryParameter, isBound) -> LOGGER.debugf(
"Checking whether parameter reference [%s] is bound : %s",
queryParameter,
isBound
)
);
}
@Override
public Object getParameterValue(String name) {
getProducer().checkOpen( false );
final QueryParameter queryParameter = getParameterMetadata().getQueryParameter( name );
return getParameterValue(
queryParameter,
(parameter) -> new IllegalStateException( "Parameter value not yet bound : " + parameter.getName() ),
(parameter, e) -> {
final String message = "Could not resolve parameter by name - " + parameter.getName();
if ( e == null ) {
return new IllegalArgumentException( message );
}
return new IllegalArgumentException( message, e );
},
(parameter, isBound) -> LOGGER.debugf(
"Checking whether positional named [%s] is bound : %s",
parameter.getName(),
isBound
)
);
}
@Override
public Object getParameterValue(int position) {
getProducer().checkOpen( false );
final QueryParameter queryParameter = getParameterMetadata().getQueryParameter( position );
return getParameterValue(
queryParameter,
(parameter) -> new IllegalStateException( "Parameter value not yet bound : " + parameter.getPosition() ),
(parameter, e) -> {
String message = "Could not resolve parameter by position - " + parameter.getPosition();
if ( e == null ) {
return new IllegalArgumentException( message );
}
return new IllegalArgumentException( message, e );
},
(parameter, isBound) -> LOGGER.debugf(
"Checking whether positional parameter [%s] is bound : %s",
parameter.getPosition(),
isBound
)
);
}
private Object getParameterValue(
QueryParameter queryParameter,
Function notBoundParamenterException,
BiFunction couldNotResolveParameterException,
BiConsumer boundCheckingLogger) {
try {
final QueryParameterBindings parameterBindings = getQueryParameterBindings();
if ( queryParameter == null ) {
throw couldNotResolveParameterException.apply( queryParameter, null );
}
if ( parameterBindings.isMultiValuedBinding( queryParameter ) ) {
final QueryParameterListBinding queryParameterListBinding = parameterBindings
.getQueryParameterListBinding( queryParameter );
final Collection bindValues = queryParameterListBinding.getBindValues();
if ( bindValues == null ) {
throw notBoundParamenterException.apply( queryParameter );
}
return bindValues;
}
final QueryParameterBinding binding = parameterBindings.getBinding( queryParameter );
final boolean bound = binding.isBound();
boundCheckingLogger.accept( queryParameter, bound );
if ( !bound ) {
throw notBoundParamenterException.apply( queryParameter );
}
return binding.getBindValue();
}
catch (QueryParameterException e) {
throw couldNotResolveParameterException.apply( queryParameter, e );
}
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setProperties(Object bean) {
Class clazz = bean.getClass();
String[] params = getNamedParameters();
for ( String namedParam : params ) {
try {
final PropertyAccess propertyAccess = BuiltInPropertyAccessStrategies.BASIC.getStrategy().buildPropertyAccess(
clazz,
namedParam
);
final Getter getter = propertyAccess.getGetter();
final Class retType = getter.getReturnType();
final Object object = getter.get( bean );
if ( Collection.class.isAssignableFrom( retType ) ) {
setParameterList( namedParam, (Collection) object );
}
else if ( retType.isArray() ) {
setParameterList( namedParam, (Object[]) object );
}
else {
Type type = determineType( namedParam, retType );
setParameter( namedParam, object, type );
}
}
catch (PropertyNotFoundException pnfe) {
// ignore
}
}
return this;
}
protected Type determineType(String namedParam, Class retType) {
Type type = getQueryParameterBindings().getBinding( namedParam ).getBindType();
if ( type == null ) {
type = getParameterMetadata().getQueryParameter( namedParam ).getHibernateType();
}
if ( type == null ) {
type = getProducer().getFactory().resolveParameterBindType( retType );
}
return type;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setProperties(Map map) {
final String[] namedParameterNames = getNamedParameters();
for ( String paramName : namedParameterNames ) {
final Object object = map.get( paramName );
if ( object == null ) {
if ( map.containsKey( paramName ) ) {
setParameter( paramName, null, determineType( paramName, null ) );
}
}
else {
Class retType = object.getClass();
if ( Collection.class.isAssignableFrom( retType ) ) {
setParameterList( paramName, (Collection) object );
}
else if ( retType.isArray() ) {
setParameterList( paramName, (Object[]) object );
}
else {
setParameter( paramName, object, determineType( paramName, retType ) );
}
}
}
return this;
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setResultTransformer(ResultTransformer transformer) {
this.resultTransformer = transformer;
return this;
}
@Override
public RowSelection getQueryOptions() {
return queryOptions;
}
@Override
public int getMaxResults() {
getProducer().checkOpen();
// to be JPA compliant this method returns an int - specifically the "magic number" Integer.MAX_VALUE defined by the spec.
// For access to the Integer (for checking), use #getQueryOptions#getMaxRows instead
return queryOptions.getMaxRows() == null ? Integer.MAX_VALUE : queryOptions.getMaxRows();
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setMaxResults(int maxResult) {
getProducer().checkOpen();
if ( maxResult < 0 ) {
throw new IllegalArgumentException( "max-results cannot be negative" );
}
else {
queryOptions.setMaxRows( maxResult );
}
return this;
}
@Override
public int getFirstResult() {
getProducer().checkOpen();
// to be JPA compliant this method returns an int - specifically the "magic number" 0 (ZERO) defined by the spec.
// For access to the Integer (for checking), use #getQueryOptions#getFirstRow instead
return queryOptions.getFirstRow() == null ? 0 : queryOptions.getFirstRow();
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setFirstResult(int startPosition) {
getProducer().checkOpen();
if ( startPosition < 0 ) {
throw new IllegalArgumentException( "first-result value cannot be negative : " + startPosition );
}
queryOptions.setFirstRow( startPosition );
return this;
}
@SuppressWarnings( {"UnusedDeclaration"})
public Set getSupportedHints() {
return QueryHints.getDefinedHints();
}
@Override
public Map getHints() {
// Technically this should rollback, but that's insane :)
// If the TCK ever adds a check for this, we may need to change this behavior
getProducer().checkOpen( false );
final Map hints = new HashMap<>();
collectBaselineHints( hints );
collectHints( hints );
return hints;
}
protected void collectBaselineHints(Map hints) {
// nothing to do in this form
}
protected void collectHints(Map hints) {
final RowSelection queryOptions = getQueryOptions();
final Integer queryTimeout = queryOptions.getTimeout();
if ( queryTimeout != null ) {
hints.put( HINT_TIMEOUT, queryTimeout );
hints.put( SPEC_HINT_TIMEOUT, queryTimeout * 1000 );
}
final LockOptions lockOptions = getLockOptions();
final int lockOptionsTimeOut = lockOptions.getTimeOut();
if ( lockOptionsTimeOut != WAIT_FOREVER ) {
hints.put( JPA_LOCK_TIMEOUT, lockOptionsTimeOut );
}
if ( lockOptions.getScope() ) {
hints.put( JPA_LOCK_SCOPE, lockOptions.getScope() );
}
if ( lockOptions.hasAliasSpecificLockModes() && canApplyAliasSpecificLockModeHints() ) {
for ( Map.Entry entry : lockOptions.getAliasSpecificLocks() ) {
hints.put(
ALIAS_SPECIFIC_LOCK_MODE + '.' + entry.getKey(),
entry.getValue().name()
);
}
}
putIfNotNull( hints, HINT_COMMENT, getComment() );
putIfNotNull( hints, HINT_FETCH_SIZE, queryOptions.getFetchSize() );
putIfNotNull( hints, HINT_FLUSH_MODE, getHibernateFlushMode() );
if ( cacheStoreMode != null || cacheRetrieveMode != null ) {
putIfNotNull( hints, HINT_CACHE_MODE, CacheModeHelper.interpretCacheMode( cacheStoreMode, cacheRetrieveMode ) );
putIfNotNull( hints, JPA_SHARED_CACHE_RETRIEVE_MODE, cacheRetrieveMode );
putIfNotNull( hints, JPA_SHARED_CACHE_STORE_MODE, cacheStoreMode );
}
if ( isCacheable() ) {
hints.put( HINT_CACHEABLE, true );
putIfNotNull( hints, HINT_CACHE_REGION, getCacheRegion() );
}
if ( isReadOnly() ) {
hints.put( HINT_READONLY, true );
}
if ( entityGraphQueryHint != null ) {
hints.put( entityGraphQueryHint.getHintName(), entityGraphQueryHint.getOriginEntityGraph() );
}
}
protected void putIfNotNull(Map hints, String hintName, Enum hintValue) {
// centralized spot to handle the decision whether to put enums directly into the hints map
// or whether to put the enum name
if ( hintValue != null ) {
hints.put( hintName, hintValue );
// hints.put( hintName, hintValue.name() );
}
}
protected void putIfNotNull(Map hints, String hintName, Object hintValue) {
if ( hintValue != null ) {
hints.put( hintName, hintValue );
}
}
@Override
@SuppressWarnings("unchecked")
public QueryImplementor setHint(String hintName, Object value) {
getProducer().checkOpen( true );
boolean applied = false;
try {
if ( HINT_TIMEOUT.equals( hintName ) ) {
applied = applyTimeoutHint( ConfigurationHelper.getInteger( value ) );
}
else if ( SPEC_HINT_TIMEOUT.equals( hintName ) ) {
// convert milliseconds to seconds
int timeout = (int)Math.round( ConfigurationHelper.getInteger( value ).doubleValue() / 1000.0 );
applied = applyTimeoutHint( timeout );
}
else if ( JPA_LOCK_TIMEOUT.equals( hintName ) ) {
applied = applyLockTimeoutHint( ConfigurationHelper.getInteger( value ) );
}
else if ( HINT_COMMENT.equals( hintName ) ) {
applied = applyCommentHint( (String) value );
}
else if ( HINT_FETCH_SIZE.equals( hintName ) ) {
applied = applyFetchSizeHint( ConfigurationHelper.getInteger( value ) );
}
else if ( HINT_CACHEABLE.equals( hintName ) ) {
applied = applyCacheableHint( ConfigurationHelper.getBoolean( value ) );
}
else if ( HINT_CACHE_REGION.equals( hintName ) ) {
applied = applyCacheRegionHint( (String) value );
}
else if ( HINT_READONLY.equals( hintName ) ) {
applied = applyReadOnlyHint( ConfigurationHelper.getBoolean( value ) );
}
else if ( HINT_FLUSH_MODE.equals( hintName ) ) {
applied = applyFlushModeHint( ConfigurationHelper.getFlushMode( value ) );
}
else if ( HINT_CACHE_MODE.equals( hintName ) ) {
applied = applyCacheModeHint( ConfigurationHelper.getCacheMode( value ) );
}
else if ( JPA_SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) ) {
final CacheRetrieveMode retrieveMode = value != null ? CacheRetrieveMode.valueOf( value.toString() ) : null;
applied = applyJpaCacheRetrieveMode( retrieveMode );
}
else if ( JPA_SHARED_CACHE_STORE_MODE.equals( hintName ) ) {
final CacheStoreMode storeMode = value != null ? CacheStoreMode.valueOf( value.toString() ) : null;
applied = applyJpaCacheStoreMode( storeMode );
}
else if ( HINT_NATIVE_SPACES.equals( hintName ) ) {
applied = applyQuerySpaces( value );
}
else if ( QueryHints.HINT_NATIVE_LOCKMODE.equals( hintName ) ) {
applied = applyNativeQueryLockMode( value );
}
else if ( hintName.startsWith( ALIAS_SPECIFIC_LOCK_MODE ) ) {
if ( canApplyAliasSpecificLockModeHints() ) {
// extract the alias
final String alias = hintName.substring( ALIAS_SPECIFIC_LOCK_MODE.length() + 1 );
// determine the LockMode
try {
final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value );
applyAliasSpecificLockModeHint( alias, lockMode );
}
catch ( Exception e ) {
MSG_LOGGER.unableToDetermineLockModeValue( hintName, value );
applied = false;
}
}
else {
applied = false;
}
}
else if ( HINT_FETCHGRAPH.equals( hintName ) || HINT_LOADGRAPH.equals( hintName ) ) {
if ( value instanceof RootGraph ) {
applyGraph( (RootGraph) value, GraphSemantic.fromJpaHintName( hintName ) );
applyEntityGraphQueryHint( new EntityGraphQueryHint( hintName, (RootGraphImpl) value ) );
}
else {
MSG_LOGGER.warnf( "The %s hint was set, but the value was not an EntityGraph!", hintName );
}
applied = true;
}
else if ( HINT_FOLLOW_ON_LOCKING.equals( hintName ) ) {
applied = applyFollowOnLockingHint( ConfigurationHelper.getBoolean( value ) );
}
else if ( QueryHints.HINT_PASS_DISTINCT_THROUGH.equals( hintName ) ) {
applied = applyPassDistinctThrough( ConfigurationHelper.getBoolean( value ) );
}
else {
MSG_LOGGER.ignoringUnrecognizedQueryHint( hintName );
}
}
catch ( ClassCastException e ) {
throw new IllegalArgumentException( "Value for hint" );
}
if ( !applied ) {
handleUnrecognizedHint( hintName, value );
}
return this;
}
protected boolean applyQuerySpaces(Object value) {
throw new IllegalStateException(
"Illegal attempt to apply native-query spaces to a non-native query"
);
}
protected void handleUnrecognizedHint(String hintName, Object value) {
MSG_LOGGER.debugf( "Skipping unsupported query hint [%s]", hintName );
}
protected boolean applyJpaCacheRetrieveMode(CacheRetrieveMode mode) {
this.cacheRetrieveMode = mode;
return true;
}
protected boolean applyJpaCacheStoreMode(CacheStoreMode storeMode) {
this.cacheStoreMode = storeMode;
return true;
}
protected boolean applyNativeQueryLockMode(Object value) {
if ( !isNativeQuery() ) {
throw new IllegalStateException(
"Illegal attempt to set lock mode on non-native query via hint; use Query#setLockMode instead"
);
}
return false;
}
/**
* Apply the query timeout hint.
*
* @param timeout The timeout (in seconds!) specified as a hint
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyTimeoutHint(int timeout) {
setTimeout( timeout );
return true;
}
/**
* Apply the lock timeout (in seconds!) hint
*
* @param timeout The timeout (in seconds!) specified as a hint
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyLockTimeoutHint(int timeout) {
getLockOptions().setTimeOut( timeout );
return true;
}
/**
* Apply the comment hint.
*
* @param comment The comment specified as a hint
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyCommentHint(String comment) {
setComment( comment );
return true;
}
/**
* Apply the fetch size hint
*
* @param fetchSize The fetch size specified as a hint
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyFetchSizeHint(int fetchSize) {
setFetchSize( fetchSize );
return true;
}
/**
* Apply the cacheable (true/false) hint.
*
* @param isCacheable The value specified as hint
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyCacheableHint(boolean isCacheable) {
setCacheable( isCacheable );
return true;
}
/**
* Apply the cache region hint
*
* @param regionName The name of the cache region specified as a hint
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyCacheRegionHint(String regionName) {
setCacheRegion( regionName );
return true;
}
/**
* Apply the read-only (true/false) hint.
*
* @param isReadOnly The value specified as hint
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyReadOnlyHint(boolean isReadOnly) {
setReadOnly( isReadOnly );
return true;
}
/**
* Apply the CacheMode hint.
*
* @param cacheMode The CacheMode value specified as a hint.
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyCacheModeHint(CacheMode cacheMode) {
setCacheMode( cacheMode );
return true;
}
/**
* Apply the FlushMode hint.
*
* @param flushMode The FlushMode value specified as hint
*
* @return {@code true} if the hint was "applied"
*/
protected boolean applyFlushModeHint(FlushMode flushMode) {
setFlushMode( flushMode );
return true;
}
/**
* Can alias-specific lock modes be applied?
*
* @return {@code true} indicates they can be applied, {@code false} otherwise.
*/
protected boolean canApplyAliasSpecificLockModeHints() {
// only procedure/function calls cannot I believe
return true;
}
protected boolean applyLockModeTypeHint(LockModeType lockModeType) {
getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
return true;
}
protected boolean applyHibernateLockModeHint(LockMode lockMode) {
getLockOptions().setLockMode( lockMode );
return true;
}
/**
* Apply the alias specific lock modes. Assumes {@link #canApplyAliasSpecificLockModeHints()} has already been
* called and returned {@code true}.
*
* @param alias The alias to apply the 'lockMode' to.
* @param lockMode The LockMode to apply.
*/
protected void applyAliasSpecificLockModeHint(String alias, LockMode lockMode) {
getLockOptions().setAliasSpecificLockMode( alias, lockMode );
}
@Override
public Query applyGraph(RootGraph graph, GraphSemantic semantic) {
if ( semantic == null ) {
this.entityGraphQueryHint = null;
}
else {
if ( graph == null ) {
throw new IllegalStateException( "Semantic was non-null, but graph was null" );
}
applyEntityGraphQueryHint( new EntityGraphQueryHint( (RootGraphImplementor>) graph, semantic ) );
}
return this;
}
/**
* Used from HEM code as a (hopefully temporary) means to apply a custom query plan
* in regards to a JPA entity graph.
*
* @param hint The entity graph hint object
*
* @deprecated (5.4) Use {@link #applyGraph} instead
*/
@Deprecated
protected void applyEntityGraphQueryHint(EntityGraphQueryHint hint) {
this.entityGraphQueryHint = hint;
}
/**
* Apply the follow-on-locking hint.
*
* @param followOnLocking The follow-on-locking strategy.
*/
protected boolean applyFollowOnLockingHint(Boolean followOnLocking) {
getLockOptions().setFollowOnLocking( followOnLocking );
return true;
}
/**
* Apply the follow-on-locking hint.
*
* @param passDistinctThrough the query passes {@code distinct} to the database
*/
protected boolean applyPassDistinctThrough(boolean passDistinctThrough) {
this.passDistinctThrough = passDistinctThrough;
return true;
}
/**
* Is the query represented here a native (SQL) query?
*
* @return {@code true} if it is a native query; {@code false} otherwise
*/
protected abstract boolean isNativeQuery();
@Override
public LockModeType getLockMode() {
getProducer().checkOpen( false );
if ( !isSelect() ) {
throw new IllegalStateException( "Illegal attempt to get lock mode on a non-SELECT query" );
}
return LockModeTypeHelper.getLockModeType( lockOptions.getLockMode() );
}
@Override
@SuppressWarnings("unchecked")
public T unwrap(Class cls) {
if ( cls.isInstance( getProducer() ) ) {
return (T) getProducer();
}
if ( cls.isInstance( getParameterMetadata() ) ) {
return (T) getParameterMetadata();
}
if ( cls.isInstance( getQueryParameterBindings() ) ) {
return (T) getQueryParameterBindings();
}
if ( cls.isInstance( this ) ) {
return (T) this;
}
throw new HibernateException( "Could not unwrap this [" + toString() + "] as requested Java type [" + cls.getName() + "]" );
// throw new IllegalArgumentException( "Could not unwrap this [" + toString() + "] as requested Java type [" + cls.getName() + "]" );
}
protected QueryParameters makeQueryParametersForExecution(String hql) {
final HQLQueryPlan entityGraphHintedQueryPlan;
if ( entityGraphQueryHint == null) {
entityGraphHintedQueryPlan = null;
}
else {
final SharedSessionContractImplementor producer = getProducer();
entityGraphHintedQueryPlan = new HQLQueryPlan(
hql,
false,
producer.getLoadQueryInfluencers().getEnabledFilters(),
producer.getFactory(),
entityGraphQueryHint
);
}
QueryParameters queryParameters = new QueryParameters(
getQueryParameterBindings(),
getLockOptions(),
queryOptions,
true,
isReadOnly(),
cacheable,
cacheRegion,
comment,
dbHints,
null,
optionalObject,
optionalEntityName,
optionalId,
resultTransformer
);
queryParameters.setQueryPlan( entityGraphHintedQueryPlan );
if ( passDistinctThrough != null ) {
queryParameters.setPassDistinctThrough( passDistinctThrough );
}
return queryParameters;
}
public QueryParameters getQueryParameters() {
final String expandedQuery = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getProducer() );
return makeQueryParametersForExecution( expandedQuery );
}
@SuppressWarnings("deprecation")
protected Type[] getPositionalParameterTypes() {
return getQueryParameterBindings().collectPositionalBindTypes();
}
@SuppressWarnings("deprecation")
protected Object[] getPositionalParameterValues() {
return getQueryParameterBindings().collectPositionalBindValues();
}
@SuppressWarnings("deprecation")
protected Map getNamedParameterMap() {
return getQueryParameterBindings().collectNamedParameterBindings();
}
private FlushMode sessionFlushMode;
private CacheMode sessionCacheMode;
protected void beforeQuery() {
if ( optionalId == null ) {
getQueryParameterBindings().verifyParametersBound( isCallable() );
}
assert sessionFlushMode == null;
assert sessionCacheMode == null;
if ( flushMode != null ) {
sessionFlushMode = getProducer().getHibernateFlushMode();
getProducer().setHibernateFlushMode( flushMode );
}
final CacheMode effectiveCacheMode = CacheModeHelper.effectiveCacheMode( cacheStoreMode, cacheRetrieveMode );
if ( effectiveCacheMode != null ) {
sessionCacheMode = getProducer().getCacheMode();
getProducer().setCacheMode( effectiveCacheMode );
}
if ( entityGraphQueryHint != null && entityGraphQueryHint.getSemantic() == GraphSemantic.FETCH ) {
getProducer().setEnforcingFetchGraph( true );
}
}
protected void afterQuery() {
if ( sessionFlushMode != null ) {
getProducer().setHibernateFlushMode( sessionFlushMode );
sessionFlushMode = null;
}
if ( sessionCacheMode != null ) {
getProducer().setCacheMode( sessionCacheMode );
sessionCacheMode = null;
}
getProducer().setEnforcingFetchGraph( false );
}
@Override
public Iterator iterate() {
beforeQuery();
try {
return doIterate();
}
finally {
afterQuery();
}
}
@SuppressWarnings("unchecked")
protected Iterator doIterate() {
if (getMaxResults() == 0){
return Collections.emptyIterator();
}
return getProducer().iterate(
getQueryParameterBindings().expandListValuedParameters( getQueryString(), getProducer() ),
getQueryParameters()
);
}
@Override
public ScrollableResultsImplementor scroll() {
return scroll( getProducer().getJdbcServices().getJdbcEnvironment().getDialect().defaultScrollMode() );
}
@Override
public ScrollableResultsImplementor scroll(ScrollMode scrollMode) {
beforeQuery();
try {
return doScroll( scrollMode );
}
finally {
afterQuery();
}
}
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
if (getMaxResults() == 0){
return EmptyScrollableResults.INSTANCE;
}
final String query = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getProducer() );
QueryParameters queryParameters = makeQueryParametersForExecution( query );
queryParameters.setScrollMode( scrollMode );
return getProducer().scroll( query, queryParameters );
}
@Override
@SuppressWarnings("unchecked")
public Stream stream() {
if (getMaxResults() == 0){
final Spliterator spliterator = Spliterators.emptySpliterator();
return StreamSupport.stream( spliterator, false );
}
final ScrollableResultsImplementor scrollableResults = scroll( ScrollMode.FORWARD_ONLY );
final ScrollableResultsIterator iterator = new ScrollableResultsIterator<>( scrollableResults );
final Spliterator spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL );
final Stream stream = new StreamDecorator(
StreamSupport.stream( spliterator, false ),
scrollableResults::close
);
return stream;
}
@Override
public Optional uniqueResultOptional() {
return Optional.ofNullable( uniqueResult() );
}
@Override
public List list() {
beforeQuery();
try {
return doList();
}
catch (QueryExecutionRequestException he) {
throw new IllegalStateException( he );
}
catch (TypeMismatchException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw getExceptionConverter().convert( he, getLockOptions() );
}
finally {
afterQuery();
}
}
protected boolean isCallable() {
return false;
}
@SuppressWarnings("unchecked")
protected List doList() {
if ( getMaxResults() == 0 ) {
return Collections.EMPTY_LIST;
}
if ( lockOptions.getLockMode() != null && lockOptions.getLockMode() != LockMode.NONE ) {
if ( !getProducer().isTransactionInProgress() ) {
throw new TransactionRequiredException( "no transaction is in progress" );
}
}
final String expandedQuery = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getProducer() );
return getProducer().list(
expandedQuery,
makeQueryParametersForExecution( expandedQuery )
);
}
protected abstract QueryParameterBindings getQueryParameterBindings();
@Override
public R uniqueResult() {
return uniqueElement( list() );
}
@Override
public R getSingleResult() {
try {
final List list = list();
if ( list.size() == 0 ) {
throw new NoResultException( "No entity found for query" );
}
return uniqueElement( list );
}
catch ( HibernateException e ) {
throw getExceptionConverter().convert( e, getLockOptions() );
}
}
public static R uniqueElement(List list) throws NonUniqueResultException {
int size = list.size();
if ( size == 0 ) {
return null;
}
R first = list.get( 0 );
for ( int i = 1; i < size; i++ ) {
if ( list.get( i ) != first ) {
throw new NonUniqueResultException( list.size() );
}
}
return first;
}
@Override
public int executeUpdate() throws HibernateException {
getProducer().checkTransactionNeededForUpdateOperation( "Executing an update/delete query" );
beforeQuery();
try {
return doExecuteUpdate();
}
catch ( QueryExecutionRequestException e) {
throw new IllegalStateException( e );
}
catch( TypeMismatchException e ) {
throw new IllegalArgumentException( e );
}
catch ( HibernateException e) {
throw getExceptionConverter().convert( e );
}
finally {
afterQuery();
}
}
protected int doExecuteUpdate() {
final String expandedQuery = getQueryParameterBindings().expandListValuedParameters( getQueryString(), getProducer() );
return getProducer().executeUpdate(
expandedQuery,
makeQueryParametersForExecution( expandedQuery )
);
}
protected String resolveEntityName(Object val) {
if ( val == null ) {
throw new IllegalArgumentException( "entity for parameter binding cannot be null" );
}
return getProducer().bestGuessEntityName( val );
}
@Override
public void setOptionalEntityName(String optionalEntityName) {
this.optionalEntityName = optionalEntityName;
}
@Override
public void setOptionalId(Serializable optionalId) {
this.optionalId = optionalId;
}
@Override
public void setOptionalObject(Object optionalObject) {
this.optionalObject = optionalObject;
}
@Override
@SuppressWarnings("unchecked")
public Type determineProperBooleanType(String name, Object value, Type defaultType) {
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( name );
return binding.getBindType() != null
? binding.getBindType()
: defaultType;
}
@Override
public Type determineProperBooleanType(int position, Object value, Type defaultType) {
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( position );
return binding.getBindType() != null
? binding.getBindType()
: defaultType;
}
private boolean isSelect() {
return getProducer().getFactory().getQueryPlanCache()
.getHQLQueryPlan( getQueryString(), false, Collections.emptyMap() )
.isSelect();
}
protected ExceptionConverter getExceptionConverter(){
return producer.getExceptionConverter();
}
private boolean isRegisteredAsBasicType(Class cl) {
return producer.getFactory().getTypeResolver().basic( cl.getName() ) != null;
}
}