6 - SQM based on JPA type system
- further work on `org.hibernate.query` (especially `NamedQueryRepository` and friends) - initial work on `org.hibernate.sql.exec` - initial work on `org.hibernate.sql.results` - SemanticPathPart handling
This commit is contained in:
parent
fb12f3a60f
commit
2167abd373
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate;
|
||||
|
||||
/**
|
||||
* Hibernate often deals with compound names/paths. This interface
|
||||
* defines a standard way of interacting with them
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DotIdentifierSequence {
|
||||
DotIdentifierSequence getParent();
|
||||
String getLocalName();
|
||||
String getFullPath();
|
||||
|
||||
DotIdentifierSequence append(String subPathName);
|
||||
|
||||
default boolean isRoot() {
|
||||
return getParent() == null;
|
||||
}
|
||||
}
|
|
@ -43,7 +43,7 @@ import org.hibernate.mapping.MappedSuperclass;
|
|||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.procedure.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.query.spi.NamedQueryRepository;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeResolver;
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.ParameterMode;
|
||||
import javax.persistence.StoredProcedureParameter;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.boot.spi.AbstractNamedQueryMapping;
|
||||
import org.hibernate.boot.spi.NamedCallableQueryMapping;
|
||||
import org.hibernate.boot.spi.NamedQueryParameterMapping;
|
||||
import org.hibernate.cfg.BinderHelper;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.procedure.internal.NamedCallableQueryMementoImpl;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
||||
import org.hibernate.query.procedure.internal.ProcedureParameterImpl;
|
||||
import org.hibernate.query.spi.ParameterMemento;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedCallableQueryMappingImpl extends AbstractNamedQueryMapping implements NamedCallableQueryMapping {
|
||||
private final String callableName;
|
||||
private final List<String> resultSetMappingNames;
|
||||
private final List<Class> resultClasses;
|
||||
private final Set<String> querySpaces;
|
||||
|
||||
public NamedCallableQueryMappingImpl(
|
||||
String name,
|
||||
String callableName,
|
||||
List<NamedQueryParameterMapping> parameterMappings,
|
||||
List<Class> resultClasses,
|
||||
List<String> resultSetMappingNames,
|
||||
Set<String> querySpaces,
|
||||
Boolean cacheable,
|
||||
String cacheRegion,
|
||||
CacheMode cacheMode,
|
||||
FlushMode flushMode,
|
||||
Boolean readOnly,
|
||||
LockOptions lockOptions,
|
||||
Integer timeout,
|
||||
Integer fetchSize,
|
||||
String comment,
|
||||
Map<String,Object> hints) {
|
||||
super(
|
||||
name,
|
||||
parameterMappings,
|
||||
cacheable,
|
||||
cacheRegion,
|
||||
cacheMode,
|
||||
flushMode,
|
||||
readOnly,
|
||||
lockOptions,
|
||||
timeout,
|
||||
fetchSize,
|
||||
comment,
|
||||
hints
|
||||
);
|
||||
|
||||
this.callableName = callableName;
|
||||
this.resultSetMappingNames = resultSetMappingNames;
|
||||
this.resultClasses = resultClasses;
|
||||
this.querySpaces = querySpaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedCallableQueryMemento resolve(SessionFactoryImplementor factory) {
|
||||
return new NamedCallableQueryMementoImpl(
|
||||
getName(),
|
||||
callableName,
|
||||
ParameterStrategy.UNKNOWN,
|
||||
resolveParameterMappings( factory ),
|
||||
resultClasses,
|
||||
resultSetMappingNames,
|
||||
querySpaces,
|
||||
getCacheable(),
|
||||
getCacheRegion(),
|
||||
getCacheMode(),
|
||||
getFlushMode(),
|
||||
getReadOnly(),
|
||||
getLockOptions(),
|
||||
getTimeout(),
|
||||
getFetchSize(),
|
||||
getComment(),
|
||||
getHints()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends NamedCallableQueryMementoImpl.CallableParameterMemento> resolveParameterMappings(SessionFactoryImplementor factory) {
|
||||
//noinspection unchecked
|
||||
return (List) super.resolveParameterMappings( factory );
|
||||
}
|
||||
|
||||
public static class Builder extends AbstractBuilder<Builder> {
|
||||
private String callableName;
|
||||
|
||||
private List<Class> resultClasses;
|
||||
private List<String> resultSetMappingNames;
|
||||
|
||||
private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN;
|
||||
private List<NamedCallableQueryParameterMapping> parameterMappings;
|
||||
|
||||
public Builder(String name) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Builder getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder consume(StoredProcedureParameter[] parameters) {
|
||||
if ( parameters != null && parameters.length > 0 ) {
|
||||
for ( StoredProcedureParameter parameter : parameters ) {
|
||||
consume( parameter );
|
||||
}
|
||||
}
|
||||
return getThis();
|
||||
}
|
||||
|
||||
private void consume(StoredProcedureParameter parameter) {
|
||||
if ( BinderHelper.isEmptyAnnotationValue( parameter.name() ) ) {
|
||||
consumeNamedParameter( parameter.name(), parameter.type(), parameter.mode() );
|
||||
}
|
||||
if ( parameter.name() != null ) {
|
||||
}
|
||||
}
|
||||
|
||||
private void consumeNamedParameter(String name, Class type, ParameterMode mode) {
|
||||
if ( parameterStrategy == ParameterStrategy.POSITIONAL ) {
|
||||
throw new IllegalArgumentException(
|
||||
"Named queries cannot mix named and positional parameters: " + getName()
|
||||
);
|
||||
}
|
||||
|
||||
parameterStrategy = ParameterStrategy.NAMED;
|
||||
final NamedCallableQueryParameterMapping namedParameter = new NamedCallableQueryParameterMapping() {
|
||||
@Override
|
||||
public ParameterMemento resolve(SessionFactoryImplementor factory) {
|
||||
return session -> new ProcedureParameterImpl(
|
||||
label,
|
||||
mode,
|
||||
javaType,
|
||||
factory.getMetamodel().getTypeConfiguration().standardBasicTypeForJavaType( javaType ),
|
||||
factory.getSessionFactoryOptions().isProcedureParameterNullPassingEnabled()
|
||||
);
|
||||
}
|
||||
};
|
||||
parameterMappings.add( namedParameter );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NamedCallableQueryParameterMapping createPositionalParameter(int label, Class javaType, ParameterMode mode) {
|
||||
return
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NamedCallableQueryParameterMapping createNamedParameter(String name, Class javaType, ParameterMode mode) {
|
||||
//noinspection Convert2Lambda
|
||||
return new NamedQueryParameterMapping() {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ParameterMemento resolve(SessionFactoryImplementor factory) {
|
||||
return session -> new ProcedureParameterImpl(
|
||||
name,
|
||||
mode,
|
||||
javaType,
|
||||
factory.getMetamodel().getTypeConfiguration().standardBasicTypeForJavaType( javaType ),
|
||||
factory.getSessionFactoryOptions().isProcedureParameterNullPassingEnabled()
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public NamedCallableQueryMapping build() {
|
||||
return new NamedCallableQueryMappingImpl(
|
||||
getName(),
|
||||
callableName,
|
||||
getParameterMappings(),
|
||||
resultClasses,
|
||||
resultSetMappingNames,
|
||||
getQuerySpaces(),
|
||||
getCacheable(),
|
||||
getCacheRegion(),
|
||||
getCacheMode(),
|
||||
getFlushMode(),
|
||||
getReadOnly(),
|
||||
getLockOptions(),
|
||||
getTimeout(),
|
||||
getFetchSize(),
|
||||
getComment(),
|
||||
getHints()
|
||||
);
|
||||
}
|
||||
|
||||
public Builder setCallableName(String callableName) {
|
||||
this.callableName = callableName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static class NamedCallableQueryParameterMapping implements NamedQueryParameterMapping {
|
||||
|
||||
@Override
|
||||
public ParameterMemento resolve(SessionFactoryImplementor factory) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.boot.spi.AbstractNamedQueryMapping;
|
||||
import org.hibernate.boot.spi.NamedHqlQueryMapping;
|
||||
import org.hibernate.boot.spi.NamedQueryParameterMapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedHqlQueryMappingImpl extends AbstractNamedQueryMapping implements NamedHqlQueryMapping {
|
||||
private final String hqlString;
|
||||
private final Integer firstResult;
|
||||
private final Integer maxResults;
|
||||
|
||||
public NamedHqlQueryMappingImpl(
|
||||
String name,
|
||||
String hqlString,
|
||||
List<NamedQueryParameterMapping> parameterMappings,
|
||||
Integer firstResult,
|
||||
Integer maxResults,
|
||||
Boolean cacheable,
|
||||
String cacheRegion,
|
||||
CacheMode cacheMode,
|
||||
FlushMode flushMode,
|
||||
Boolean readOnly,
|
||||
LockOptions lockOptions,
|
||||
Integer timeout,
|
||||
Integer fetchSize,
|
||||
String comment,
|
||||
Map<String,Object> hints) {
|
||||
super(
|
||||
name,
|
||||
parameterMappings,
|
||||
cacheable,
|
||||
cacheRegion,
|
||||
cacheMode,
|
||||
flushMode,
|
||||
readOnly,
|
||||
lockOptions,
|
||||
timeout,
|
||||
fetchSize,
|
||||
comment,
|
||||
hints
|
||||
);
|
||||
this.hqlString = hqlString;
|
||||
this.firstResult = firstResult;
|
||||
this.maxResults = maxResults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return hqlString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedHqlQueryMemento resolve(SessionFactoryImplementor factory) {
|
||||
return new NamedHqlQueryMementoImpl(
|
||||
getName(),
|
||||
hqlString,
|
||||
resolveParameterMappings( factory ),
|
||||
firstResult,
|
||||
maxResults,
|
||||
getCacheable(),
|
||||
getCacheRegion(),
|
||||
getCacheMode(),
|
||||
getFlushMode(),
|
||||
getReadOnly(),
|
||||
getLockOptions(),
|
||||
getTimeout(),
|
||||
getFetchSize(),
|
||||
getComment(),
|
||||
getHints()
|
||||
);
|
||||
}
|
||||
|
||||
public static class Builder extends AbstractBuilder<Builder> {
|
||||
private final String hqlString;
|
||||
|
||||
private Integer firstResult;
|
||||
private Integer maxResults;
|
||||
|
||||
public Builder(String name, String hqlString) {
|
||||
super( name );
|
||||
this.hqlString = hqlString;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Builder getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFirstResult(Integer firstResult) {
|
||||
this.firstResult = firstResult;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public Builder setMaxResults(Integer maxResults) {
|
||||
this.maxResults = maxResults;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NamedQueryParameterMapping createPositionalParameter(int i, Class javaType, ParameterMode mode) {
|
||||
/// todo (6.0) : this really ought to just adjust the type, if one...
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
// return new ParameterDefinition() {
|
||||
// @Override
|
||||
// public ParameterDescriptor resolve(SessionFactoryImplementor factory) {
|
||||
// return new ParameterDescriptor() {
|
||||
// @Override
|
||||
// public QueryParameter toQueryParameter(SharedSessionContractImplementor session) {
|
||||
// return new QueryParameterPositionalImpl( i, );
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NamedQueryParameterMapping createNamedParameter(String name, Class javaType, ParameterMode mode) {
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
|
||||
public NamedHqlQueryMappingImpl build() {
|
||||
return new NamedHqlQueryMappingImpl(
|
||||
getName(),
|
||||
hqlString,
|
||||
getParameterMappings(),
|
||||
firstResult,
|
||||
maxResults,
|
||||
getCacheable(),
|
||||
getCacheRegion(),
|
||||
getCacheMode(),
|
||||
getFlushMode(),
|
||||
getReadOnly(),
|
||||
getLockOptions(),
|
||||
getTimeout(),
|
||||
getFetchSize(),
|
||||
getComment(),
|
||||
getHints()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.BasicQueryContract;
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.boot.spi.AbstractNamedQueryMapping;
|
||||
import org.hibernate.boot.spi.NamedNativeQueryMapping;
|
||||
import org.hibernate.boot.spi.NamedQueryParameterMapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.spi.ParameterMemento;
|
||||
import org.hibernate.query.sql.internal.NamedNativeQueryMementoImpl;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedNativeQueryMappingImpl extends AbstractNamedQueryMapping implements NamedNativeQueryMapping {
|
||||
private final String sqlString;
|
||||
private final String resultSetMappingName;
|
||||
private final Set<String> querySpaces;
|
||||
|
||||
public NamedNativeQueryMappingImpl(
|
||||
String name,
|
||||
String sqlString,
|
||||
List<NamedQueryParameterMapping> parameterMappings,
|
||||
String resultSetMappingName,
|
||||
Set<String> querySpaces,
|
||||
Boolean cacheable,
|
||||
String cacheRegion,
|
||||
CacheMode cacheMode,
|
||||
FlushMode flushMode,
|
||||
Boolean readOnly,
|
||||
LockOptions lockOptions,
|
||||
Integer timeout,
|
||||
Integer fetchSize,
|
||||
String comment,
|
||||
Map<String,Object> hints) {
|
||||
super(
|
||||
name,
|
||||
parameterMappings,
|
||||
cacheable,
|
||||
cacheRegion,
|
||||
cacheMode,
|
||||
flushMode,
|
||||
readOnly,
|
||||
lockOptions,
|
||||
timeout,
|
||||
fetchSize,
|
||||
comment,
|
||||
hints
|
||||
);
|
||||
this.sqlString = sqlString;
|
||||
this.resultSetMappingName = resultSetMappingName;
|
||||
this.querySpaces = querySpaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return sqlString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResultSetMappingName() {
|
||||
return resultSetMappingName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMemento resolve(SessionFactoryImplementor factory) {
|
||||
return new NamedNativeQueryMementoImpl(
|
||||
getName(),
|
||||
sqlString,
|
||||
resultSetMappingName,
|
||||
resolveParameterMappings( factory ),
|
||||
querySpaces,
|
||||
getCacheable(),
|
||||
getCacheRegion(),
|
||||
getCacheMode(),
|
||||
getFlushMode(),
|
||||
getReadOnly(),
|
||||
getLockOptions(),
|
||||
getTimeout(),
|
||||
getFetchSize(),
|
||||
getComment(),
|
||||
getHints()
|
||||
);
|
||||
}
|
||||
|
||||
public static class Builder extends AbstractBuilder<Builder> {
|
||||
private String sqlString;
|
||||
|
||||
private String resultSetMappingName;
|
||||
private Class resultSetMappingClass;
|
||||
|
||||
public Builder(String name) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
public Builder setSqlString(String sqlString) {
|
||||
this.sqlString = sqlString;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public NamedNativeQueryMappingImpl build() {
|
||||
return new NamedNativeQueryMappingImpl(
|
||||
getName(),
|
||||
sqlString,
|
||||
getParameterMappings(),
|
||||
resultSetMappingName,
|
||||
getQuerySpaces(),
|
||||
getCacheable(),
|
||||
getCacheRegion(),
|
||||
getCacheMode(),
|
||||
getFlushMode(),
|
||||
getReadOnly(),
|
||||
getLockOptions(),
|
||||
getTimeout(),
|
||||
getFetchSize(),
|
||||
getComment(),
|
||||
getHints()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Builder getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NamedQueryParameterMapping createPositionalParameter(int i, Class javaType, ParameterMode mode) {
|
||||
//noinspection Convert2Lambda
|
||||
return new NamedQueryParameterMapping() {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ParameterMemento resolve(SessionFactoryImplementor factory) {
|
||||
return session -> new QueryParameterPositionalImpl(
|
||||
i,
|
||||
false,
|
||||
factory.getMetamodel().getTypeConfiguration().standardBasicTypeForJavaType( javaType )
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NamedQueryParameterMapping createNamedParameter(String name, Class javaType, ParameterMode mode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Builder setResultSetMappingName(String resultSetMappingName) {
|
||||
this.resultSetMappingName = resultSetMappingName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,12 +22,11 @@ import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType;
|
|||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmQueryParamType;
|
||||
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmSynchronizeType;
|
||||
import org.hibernate.cfg.SecondPass;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
import org.hibernate.query.spi.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
|
||||
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
|
||||
import org.hibernate.boot.spi.NamedNativeQueryMementoBuilder;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
||||
/**
|
||||
|
@ -74,7 +73,7 @@ public class NamedQueryBinder {
|
|||
);
|
||||
}
|
||||
context.getMetadataCollector().addNamedQuery(
|
||||
new NamedQueryDefinitionBuilder()
|
||||
new NamedHqlQueryMemento.Builder()
|
||||
.setName( prefix + namedQueryBinding.getName() )
|
||||
.setQuery( query )
|
||||
.setComment( namedQueryBinding.getComment() )
|
||||
|
@ -101,7 +100,7 @@ public class NamedQueryBinder {
|
|||
JaxbHbmNamedNativeQueryType namedQueryBinding,
|
||||
String prefix) {
|
||||
final String queryName = prefix + namedQueryBinding.getName();
|
||||
final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder()
|
||||
final NamedNativeQueryMementoBuilder builder = new NamedNativeQueryMementoBuilder()
|
||||
.setName( queryName )
|
||||
.setComment( namedQueryBinding.getComment() )
|
||||
.setCacheable( namedQueryBinding.isCacheable() )
|
||||
|
@ -190,7 +189,7 @@ public class NamedQueryBinder {
|
|||
|
||||
private static boolean processNamedQueryContentItem(
|
||||
Object content,
|
||||
NamedSQLQueryDefinitionBuilder builder,
|
||||
NamedNativeQueryMementoBuilder builder,
|
||||
ImplicitResultSetMappingDefinition.Builder implicitResultSetMappingBuilder,
|
||||
JaxbHbmNamedNativeQueryType namedQueryBinding,
|
||||
HbmLocalMetadataBuildingContext context) {
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.boot.internal.NamedNativeQueryMappingImpl;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.spi.ParameterMemento;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractNamedQueryMapping implements NamedQueryMapping {
|
||||
private final String name;
|
||||
|
||||
private final List<? extends NamedQueryParameterMapping> parameterMappings;
|
||||
|
||||
private final Boolean cacheable;
|
||||
private final String cacheRegion;
|
||||
private final CacheMode cacheMode;
|
||||
|
||||
private final FlushMode flushMode;
|
||||
private final Boolean readOnly;
|
||||
|
||||
private final LockOptions lockOptions;
|
||||
|
||||
private final Integer timeout;
|
||||
private final Integer fetchSize;
|
||||
|
||||
private final String comment;
|
||||
|
||||
private final Map<String,Object> hints;
|
||||
|
||||
public AbstractNamedQueryMapping(
|
||||
String name,
|
||||
List<? extends NamedQueryParameterMapping> parameterMappings,
|
||||
Boolean cacheable,
|
||||
String cacheRegion,
|
||||
CacheMode cacheMode,
|
||||
FlushMode flushMode,
|
||||
Boolean readOnly,
|
||||
LockOptions lockOptions,
|
||||
Integer timeout,
|
||||
Integer fetchSize,
|
||||
String comment,
|
||||
Map<String,Object> hints) {
|
||||
this.name = name;
|
||||
this.parameterMappings = parameterMappings == null
|
||||
? new ArrayList<>()
|
||||
: new ArrayList<>( parameterMappings );
|
||||
this.cacheable = cacheable;
|
||||
this.cacheRegion = cacheRegion;
|
||||
this.cacheMode = cacheMode;
|
||||
this.flushMode = flushMode;
|
||||
this.readOnly = readOnly;
|
||||
this.lockOptions = lockOptions;
|
||||
this.timeout = timeout;
|
||||
this.fetchSize = fetchSize;
|
||||
this.comment = comment;
|
||||
this.hints = hints == null ? new HashMap<>() : new HashMap<>( hints );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Boolean getCacheable() {
|
||||
return cacheable;
|
||||
}
|
||||
|
||||
public String getCacheRegion() {
|
||||
return cacheRegion;
|
||||
}
|
||||
|
||||
public CacheMode getCacheMode() {
|
||||
return cacheMode;
|
||||
}
|
||||
|
||||
public FlushMode getFlushMode() {
|
||||
return flushMode;
|
||||
}
|
||||
|
||||
public Boolean getReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
public LockOptions getLockOptions() {
|
||||
return lockOptions;
|
||||
}
|
||||
|
||||
public Integer getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public Integer getFetchSize() {
|
||||
return fetchSize;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public Map<String, Object> getHints() {
|
||||
return hints;
|
||||
}
|
||||
|
||||
protected List<? extends ParameterMemento> resolveParameterMappings(SessionFactoryImplementor factory) {
|
||||
final ArrayList<ParameterMemento> descriptors = new ArrayList<>();
|
||||
parameterMappings.forEach( parameterMapping -> descriptors.add( parameterMapping.resolve( factory ) ) );
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
protected static abstract class AbstractBuilder<T extends AbstractBuilder> {
|
||||
private final String name;
|
||||
|
||||
private Set<String> querySpaces;
|
||||
private Boolean cacheable;
|
||||
private String cacheRegion;
|
||||
private CacheMode cacheMode;
|
||||
|
||||
private FlushMode flushMode;
|
||||
private Boolean readOnly;
|
||||
|
||||
private LockOptions lockOptions;
|
||||
|
||||
private Integer timeout;
|
||||
private Integer fetchSize;
|
||||
|
||||
private String comment;
|
||||
|
||||
private Map<String,Object> hints;
|
||||
|
||||
public AbstractBuilder(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected abstract T getThis();
|
||||
|
||||
public T addParameter(Class javaType, ParameterMode mode) {
|
||||
return addParameter(
|
||||
createPositionalParameter(
|
||||
parameterMappings.size() + 1,
|
||||
javaType,
|
||||
mode
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract NamedQueryParameterMapping createPositionalParameter(int i, Class javaType, ParameterMode mode);
|
||||
|
||||
public <P extends NamedQueryParameterMapping> T addParameter(P parameterMapping) {
|
||||
if ( parameterMappings == null ) {
|
||||
parameterMappings = new ArrayList<>();
|
||||
}
|
||||
|
||||
parameterMappings.add( (P) parameterMapping );
|
||||
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T addParameter(String name, Class javaType, ParameterMode mode) {
|
||||
if ( parameterMappings == null ) {
|
||||
parameterMappings = new ArrayList<>();
|
||||
}
|
||||
|
||||
parameterMappings.add( createNamedParameter( name, javaType, mode ) );
|
||||
|
||||
return getThis();
|
||||
}
|
||||
|
||||
protected abstract <P extends NamedQueryParameterMapping> P createNamedParameter(String name, Class javaType, ParameterMode mode);
|
||||
|
||||
|
||||
public T addQuerySpaces(Set<String> querySpaces) {
|
||||
if ( querySpaces == null || querySpaces.isEmpty() ) {
|
||||
return getThis();
|
||||
}
|
||||
|
||||
if ( this.querySpaces == null ) {
|
||||
this.querySpaces = new HashSet<>();
|
||||
}
|
||||
this.querySpaces.addAll( querySpaces );
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T addQuerySpace(String space) {
|
||||
if ( this.querySpaces == null ) {
|
||||
this.querySpaces = new HashSet<>();
|
||||
}
|
||||
this.querySpaces.add( space );
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setQuerySpaces(Set<String> spaces) {
|
||||
this.querySpaces = spaces;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setCacheable(Boolean cacheable) {
|
||||
this.cacheable = cacheable;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setCacheRegion(String cacheRegion) {
|
||||
this.cacheRegion = cacheRegion;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setCacheMode(CacheMode cacheMode) {
|
||||
this.cacheMode = cacheMode;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setLockOptions(LockOptions lockOptions) {
|
||||
this.lockOptions = lockOptions;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setTimeout(Integer timeout) {
|
||||
this.timeout = timeout;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setFlushMode(FlushMode flushMode) {
|
||||
this.flushMode = flushMode;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setReadOnly(Boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setFetchSize(Integer fetchSize) {
|
||||
this.fetchSize = fetchSize;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setComment(String comment) {
|
||||
this.comment = comment;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public Set<String> getQuerySpaces() {
|
||||
return querySpaces;
|
||||
}
|
||||
|
||||
public Boolean getCacheable() {
|
||||
return cacheable;
|
||||
}
|
||||
|
||||
public String getCacheRegion() {
|
||||
return cacheRegion;
|
||||
}
|
||||
|
||||
public CacheMode getCacheMode() {
|
||||
return cacheMode;
|
||||
}
|
||||
|
||||
public FlushMode getFlushMode() {
|
||||
return flushMode;
|
||||
}
|
||||
|
||||
public Boolean getReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
public LockOptions getLockOptions() {
|
||||
return lockOptions;
|
||||
}
|
||||
|
||||
public Integer getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public Integer getFetchSize() {
|
||||
return fetchSize;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
protected List<? extends NamedQueryParameterMapping> getParameterMappings() {
|
||||
return parameterMappings;
|
||||
}
|
||||
|
||||
public void addHint(String name, Object value) {
|
||||
if ( hints == null ) {
|
||||
hints = new HashMap<>();
|
||||
}
|
||||
hints.put( name, value );
|
||||
}
|
||||
|
||||
public Map<String, Object> getHints() {
|
||||
return hints;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ import org.hibernate.cfg.SecondPass;
|
|||
import org.hibernate.cfg.UniqueConstraintHolder;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
import org.hibernate.query.spi.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
import org.hibernate.query.sql.spi.ResultSetMappingDescriptor;
|
||||
|
@ -140,7 +141,7 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
|
|||
*
|
||||
* @throws DuplicateMappingException If a query already exists with that name.
|
||||
*/
|
||||
void addNamedQuery(NamedHqlQueryMementoImpl query) throws DuplicateMappingException;
|
||||
void addNamedQuery(NamedHqlQueryMapping query) throws DuplicateMappingException;
|
||||
|
||||
/**
|
||||
* Adds metadata for a named SQL query to this repository.
|
||||
|
@ -149,7 +150,7 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
|
|||
*
|
||||
* @throws DuplicateMappingException If a query already exists with that name.
|
||||
*/
|
||||
void addNamedNativeQuery(NamedNativeQueryMemento query) throws DuplicateMappingException;
|
||||
void addNamedNativeQuery(NamedNativeQueryMapping query) throws DuplicateMappingException;
|
||||
|
||||
/**
|
||||
* Adds the metadata for a named SQL result set mapping to this repository.
|
||||
|
@ -269,9 +270,9 @@ public interface InFlightMetadataCollector extends Mapping, MetadataImplementor
|
|||
|
||||
void addDefaultIdentifierGenerator(IdentifierGeneratorDefinition generatorDefinition);
|
||||
|
||||
void addDefaultQuery(NamedHqlQueryMementoImpl queryDefinition);
|
||||
void addDefaultQuery(NamedHqlQueryMapping queryDefinition);
|
||||
|
||||
void addDefaultNamedNativeQuery(NamedSQLQueryDefinition query);
|
||||
void addDefaultNamedNativeQuery(NamedNativeQueryMapping query);
|
||||
|
||||
void addDefaultResultSetMapping(ResultSetMappingDescriptor definition);
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
|
||||
/**
|
||||
* Named query mapping for callable queries
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
public interface NamedCallableQueryMapping extends NamedQueryMapping {
|
||||
List<String> getResultSetMappingNames();
|
||||
List<Class> getResultSetMappingClasses();
|
||||
|
||||
@Override
|
||||
NamedCallableQueryMemento resolve(SessionFactoryImplementor factory);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
|
||||
/**
|
||||
* Named query mapping for HQL queries
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
public interface NamedHqlQueryMapping extends NamedQueryMapping {
|
||||
String getQueryString();
|
||||
|
||||
@Override
|
||||
NamedHqlQueryMemento resolve(SessionFactoryImplementor factory);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
|
||||
/**
|
||||
* Named query mapping for native queries
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
public interface NamedNativeQueryMapping extends NamedQueryMapping {
|
||||
String getQueryString();
|
||||
String getResultSetMappingName();
|
||||
|
||||
@Override
|
||||
NamedNativeQueryMemento resolve(SessionFactoryImplementor factory);
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
|
||||
/**
|
||||
* Delegate used in creating named native-sql query mementos for queries defined in
|
||||
* annotations, hbm.xml or orm.xml
|
||||
*/
|
||||
public class NamedNativeQueryMementoBuilder extends NamedHqlQueryMemento.Builder {
|
||||
private NativeSQLQueryReturn[] queryReturns;
|
||||
private Collection<String> querySpaces;
|
||||
private boolean callable;
|
||||
private String resultSetRef;
|
||||
|
||||
public NamedNativeQueryMementoBuilder() {
|
||||
}
|
||||
|
||||
public NamedNativeQueryMementoBuilder(String name) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
public NamedNativeQueryMementoBuilder setQueryReturns(NativeSQLQueryReturn[] queryReturns) {
|
||||
this.queryReturns = queryReturns;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedNativeQueryMementoBuilder setQueryReturns(List<NativeSQLQueryReturn> queryReturns) {
|
||||
if ( queryReturns != null ) {
|
||||
this.queryReturns = queryReturns.toArray( new NativeSQLQueryReturn[ queryReturns.size() ] );
|
||||
}
|
||||
else {
|
||||
this.queryReturns = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedNativeQueryMementoBuilder setQuerySpaces(List<String> querySpaces) {
|
||||
this.querySpaces = querySpaces;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedNativeQueryMementoBuilder setQuerySpaces(Collection<String> synchronizedQuerySpaces) {
|
||||
this.querySpaces = synchronizedQuerySpaces;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedNativeQueryMementoBuilder addSynchronizedQuerySpace(String table) {
|
||||
if ( this.querySpaces == null ) {
|
||||
this.querySpaces = new ArrayList<String>();
|
||||
}
|
||||
this.querySpaces.add( table );
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedNativeQueryMementoBuilder setResultSetRef(String resultSetRef) {
|
||||
this.resultSetRef = resultSetRef;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedNativeQueryMementoBuilder setCallable(boolean callable) {
|
||||
this.callable = callable;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setName(String name) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setName( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setQuery(String query) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setQuery( query );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setCacheable(boolean cacheable) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setCacheable( cacheable );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setCacheRegion(String cacheRegion) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setCacheRegion( cacheRegion );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setTimeout(Integer timeout) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setTimeout( timeout );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setFetchSize(Integer fetchSize) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setFetchSize( fetchSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setFlushMode(FlushMode flushMode) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setFlushMode( flushMode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setCacheMode(CacheMode cacheMode) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setCacheMode( cacheMode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setReadOnly(boolean readOnly) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setReadOnly( readOnly );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setComment(String comment) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setComment( comment );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder addParameterType(String name, String typeName) {
|
||||
return (NamedNativeQueryMementoBuilder) super.addParameterType( name, typeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setParameterTypes(Map parameterTypes) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setParameterTypes( parameterTypes );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setLockOptions(LockOptions lockOptions) {
|
||||
// todo : maybe throw an exception here instead? since this is not valid for native-0sql queries?
|
||||
return (NamedNativeQueryMementoBuilder) super.setLockOptions( lockOptions );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setFirstResult(Integer firstResult) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setFirstResult( firstResult );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMementoBuilder setMaxResults(Integer maxResults) {
|
||||
return (NamedNativeQueryMementoBuilder) super.setMaxResults( maxResults );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMemento createNamedQueryDefinition() {
|
||||
return new NamedSQLQueryDefinition(
|
||||
name,
|
||||
query,
|
||||
cacheable,
|
||||
cacheRegion,
|
||||
timeout,
|
||||
fetchSize,
|
||||
flushMode,
|
||||
cacheMode,
|
||||
readOnly,
|
||||
comment,
|
||||
parameterTypes,
|
||||
firstResult,
|
||||
maxResults,
|
||||
resultSetRef,
|
||||
querySpacesCopy(),
|
||||
callable,
|
||||
queryReturns
|
||||
);
|
||||
}
|
||||
|
||||
private List<String> querySpacesCopy() {
|
||||
return querySpaces == null
|
||||
? null
|
||||
: new ArrayList<String>( querySpaces );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.spi.NamedQueryMemento;
|
||||
|
||||
/**
|
||||
* Common attributes shared across the mapping of named HQL, native
|
||||
* and "callable" queries defined in annotations, orm.xml and hbm.xml
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
public interface NamedQueryMapping {
|
||||
/**
|
||||
* The name of the query
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Resolve the mapping definition into its run-time memento form
|
||||
*/
|
||||
NamedQueryMemento resolve(SessionFactoryImplementor factory);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.boot.spi;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.spi.ParameterMemento;
|
||||
|
||||
/**
|
||||
* Describes a parameter defined in the mapping of a {@link NamedQueryMapping}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
public interface NamedQueryParameterMapping {
|
||||
/**
|
||||
* Resolve the mapping definition into its run-time memento form
|
||||
*/
|
||||
ParameterMemento resolve(SessionFactoryImplementor factory);
|
||||
}
|
|
@ -23,7 +23,7 @@ import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.SessionFactoryImpl;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.procedure.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.internal.NamedCallableQueryMementoImpl;
|
||||
import org.hibernate.procedure.internal.Util;
|
||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
||||
|
@ -49,7 +49,7 @@ public class NamedProcedureCallDefinition {
|
|||
NamedProcedureCallDefinition(NamedStoredProcedureQuery annotation) {
|
||||
this.registeredName = annotation.name();
|
||||
this.procedureName = annotation.procedureName();
|
||||
this.hints = new QueryHintDefinition( annotation.hints() ).getHintsMap();
|
||||
this.hints = new QueryHintDefinition( queryName, annotation.hints() ).getHintsMap();
|
||||
this.resultClasses = annotation.resultClasses();
|
||||
this.resultSetMappings = annotation.resultSetMappings();
|
||||
|
||||
|
|
|
@ -23,15 +23,19 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.annotations.CacheModeType;
|
||||
import org.hibernate.annotations.FlushModeType;
|
||||
import org.hibernate.annotations.QueryHints;
|
||||
import org.hibernate.boot.internal.NamedHqlQueryMappingImpl;
|
||||
import org.hibernate.boot.internal.NamedNativeQueryMappingImpl;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.boot.spi.NamedHqlQueryMapping;
|
||||
import org.hibernate.boot.spi.NamedNativeQueryMapping;
|
||||
import org.hibernate.cfg.BinderHelper;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
||||
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
|
||||
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
|
||||
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
|
||||
import org.hibernate.boot.spi.NamedNativeQueryMementoBuilder;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -47,36 +51,40 @@ public abstract class QueryBinder {
|
|||
NamedQuery queryAnn,
|
||||
MetadataBuildingContext context,
|
||||
boolean isDefault) {
|
||||
if ( queryAnn == null ) return;
|
||||
if ( queryAnn == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
|
||||
throw new AnnotationException( "A named query must have a name when used in class or package level" );
|
||||
}
|
||||
//EJBQL Query
|
||||
QueryHintDefinition hints = new QueryHintDefinition( queryAnn.hints() );
|
||||
String queryName = queryAnn.query();
|
||||
NamedHqlQueryMementoImpl queryDefinition = new NamedQueryDefinitionBuilder( queryAnn.name() )
|
||||
.setLockOptions( hints.determineLockOptions( queryAnn ) )
|
||||
.setQuery( queryName )
|
||||
.setCacheable( hints.getBoolean( queryName, QueryHints.CACHEABLE ) )
|
||||
.setCacheRegion( hints.getString( queryName, QueryHints.CACHE_REGION ) )
|
||||
.setTimeout( hints.getTimeout( queryName ) )
|
||||
.setFetchSize( hints.getInteger( queryName, QueryHints.FETCH_SIZE ) )
|
||||
.setFlushMode( hints.getFlushMode( queryName ) )
|
||||
.setCacheMode( hints.getCacheMode( queryName ) )
|
||||
.setReadOnly( hints.getBoolean( queryName, QueryHints.READ_ONLY ) )
|
||||
.setComment( hints.getString( queryName, QueryHints.COMMENT ) )
|
||||
.setParameterTypes( null )
|
||||
.createNamedQueryDefinition();
|
||||
|
||||
if ( isDefault ) {
|
||||
context.getMetadataCollector().addDefaultQuery( queryDefinition );
|
||||
}
|
||||
else {
|
||||
context.getMetadataCollector().addNamedQuery( queryDefinition );
|
||||
}
|
||||
final String queryName = queryAnn.name();
|
||||
final String queryString = queryAnn.query();
|
||||
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf( "Binding named query: %s => %s", queryDefinition.getName(), queryDefinition.getQueryString() );
|
||||
LOG.debugf( "Binding named query: %s => %s", queryName, queryString );
|
||||
}
|
||||
|
||||
final QueryHintDefinition hints = new QueryHintDefinition( queryName, queryAnn.hints() );
|
||||
|
||||
final NamedHqlQueryMapping queryMapping = new NamedHqlQueryMappingImpl.Builder( queryName, queryString )
|
||||
.setCacheable( hints.getCacheability() )
|
||||
.setCacheMode( hints.getCacheMode() )
|
||||
.setCacheRegion( hints.getString( QueryHints.CACHE_REGION ) )
|
||||
.setTimeout( hints.getTimeout() )
|
||||
.setFetchSize( hints.getInteger( QueryHints.FETCH_SIZE ) )
|
||||
.setFlushMode( hints.getFlushMode() )
|
||||
.setReadOnly( hints.getBoolean( QueryHints.READ_ONLY ) )
|
||||
.setLockOptions( hints.determineLockOptions( queryAnn ) )
|
||||
.setComment( hints.getString( QueryHints.COMMENT ) )
|
||||
.build();
|
||||
|
||||
if ( isDefault ) {
|
||||
context.getMetadataCollector().addDefaultQuery( queryMapping );
|
||||
}
|
||||
else {
|
||||
context.getMetadataCollector().addNamedQuery( queryMapping );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,28 +94,35 @@ public abstract class QueryBinder {
|
|||
NamedNativeQuery queryAnn,
|
||||
MetadataBuildingContext context,
|
||||
boolean isDefault) {
|
||||
if ( queryAnn == null ) return;
|
||||
//ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
|
||||
if ( queryAnn == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( BinderHelper.isEmptyAnnotationValue( queryAnn.name() ) ) {
|
||||
throw new AnnotationException( "A named query must have a name when used in class or package level" );
|
||||
}
|
||||
|
||||
final String queryName = queryAnn.name();
|
||||
final String queryString = queryAnn.query();
|
||||
|
||||
//ResultSetMappingDefinition mappingDefinition = mappings.getResultSetMapping( queryAnn.resultSetMapping() );
|
||||
String resultSetMapping = queryAnn.resultSetMapping();
|
||||
QueryHintDefinition hints = new QueryHintDefinition( queryAnn.hints() );
|
||||
String queryName = queryAnn.query();
|
||||
|
||||
NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder( queryAnn.name() )
|
||||
.setQuery( queryName )
|
||||
QueryHintDefinition hints = new QueryHintDefinition( queryName, queryAnn.hints() );
|
||||
|
||||
new NamedNativeQueryMappingImpl.Builder( queryName )
|
||||
.setSqlString( queryString )
|
||||
// todo (6.0) : add support for supplying synchronized query-spaces
|
||||
.setQuerySpaces( null )
|
||||
.setCacheable( hints.getBoolean( queryName, QueryHints.CACHEABLE ) )
|
||||
.setCacheRegion( hints.getString( queryName, QueryHints.CACHE_REGION ) )
|
||||
.setTimeout( hints.getTimeout( queryName ) )
|
||||
.setFetchSize( hints.getInteger( queryName, QueryHints.FETCH_SIZE ) )
|
||||
.setFlushMode( hints.getFlushMode( queryName ) )
|
||||
.setCacheMode( hints.getCacheMode( queryName ) )
|
||||
.setReadOnly( hints.getBoolean( queryName, QueryHints.READ_ONLY ) )
|
||||
.setCacheable( hints.getCacheability() )
|
||||
.setCacheMode( hints.getCacheMode() )
|
||||
.setCacheRegion( hints.getString( QueryHints.CACHE_REGION ) )
|
||||
.setTimeout( hints.getTimeout() )
|
||||
.setFetchSize( hints.getInteger( QueryHints.FETCH_SIZE ) )
|
||||
.setFlushMode( hints.getFlushMode() )
|
||||
.setReadOnly( hints.getBoolean( QueryHints.READ_ONLY ) )
|
||||
.setComment( hints.getString( queryName, QueryHints.COMMENT ) )
|
||||
.setParameterTypes( null )
|
||||
.setCallable( hints.getBoolean( queryName, QueryHints.CALLABLE ) );
|
||||
.bu
|
||||
|
||||
if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
|
||||
//sql result set usage
|
||||
|
@ -124,9 +139,9 @@ public abstract class QueryBinder {
|
|||
else {
|
||||
builder.setQueryReturns( new NativeSQLQueryReturn[0] );
|
||||
}
|
||||
|
||||
|
||||
NamedSQLQueryDefinition query = builder.createNamedQueryDefinition();
|
||||
|
||||
|
||||
if ( isDefault ) {
|
||||
context.getMetadataCollector().addDefaultNamedNativeQuery( query );
|
||||
}
|
||||
|
@ -154,7 +169,7 @@ public abstract class QueryBinder {
|
|||
String resultSetMapping = queryAnn.resultSetMapping();
|
||||
if ( !BinderHelper.isEmptyAnnotationValue( resultSetMapping ) ) {
|
||||
//sql result set usage
|
||||
query = new NamedSQLQueryDefinitionBuilder().setName( queryAnn.name() )
|
||||
query = new NamedNativeQueryMementoBuilder().setName( queryAnn.name() )
|
||||
.setQuery( queryAnn.query() )
|
||||
.setResultSetRef( resultSetMapping )
|
||||
.setQuerySpaces( null )
|
||||
|
@ -179,7 +194,7 @@ public abstract class QueryBinder {
|
|||
//FIXME should be done in a second pass due to entity name?
|
||||
final NativeSQLQueryRootReturn entityQueryReturn =
|
||||
new NativeSQLQueryRootReturn( "alias1", queryAnn.resultClass().getName(), new HashMap(), LockMode.READ );
|
||||
query = new NamedSQLQueryDefinitionBuilder().setName( queryAnn.name() )
|
||||
query = new NamedNativeQueryMementoBuilder().setName( queryAnn.name() )
|
||||
.setQuery( queryAnn.query() )
|
||||
.setQueryReturns( new NativeSQLQueryReturn[] {entityQueryReturn} )
|
||||
.setQuerySpaces( null )
|
||||
|
@ -257,7 +272,7 @@ public abstract class QueryBinder {
|
|||
FlushMode flushMode;
|
||||
flushMode = getFlushMode( queryAnn.flushMode() );
|
||||
|
||||
NamedHqlQueryMementoImpl query = new NamedQueryDefinitionBuilder().setName( queryAnn.name() )
|
||||
NamedHqlQueryMementoImpl query = new NamedHqlQueryMemento.Builder().setName( queryAnn.name() )
|
||||
.setQuery( queryAnn.query() )
|
||||
.setCacheable( queryAnn.cacheable() )
|
||||
.setCacheRegion(
|
||||
|
|
|
@ -21,19 +21,23 @@ import org.hibernate.LockOptions;
|
|||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.QueryHints;
|
||||
import org.hibernate.internal.util.LockModeConverter;
|
||||
import org.hibernate.internal.util.config.ConfigurationException;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
||||
/**
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class QueryHintDefinition {
|
||||
private final String queryName;
|
||||
private final Map<String, Object> hintsMap;
|
||||
|
||||
public QueryHintDefinition(final QueryHint[] hints) {
|
||||
public QueryHintDefinition(String queryName, final QueryHint[] hints) {
|
||||
this.queryName = queryName;
|
||||
if ( hints == null || hints.length == 0 ) {
|
||||
hintsMap = Collections.emptyMap();
|
||||
}
|
||||
else {
|
||||
final Map<String, Object> hintsMap = new HashMap<String, Object>();
|
||||
final Map<String, Object> hintsMap = new HashMap<>();
|
||||
for ( QueryHint hint : hints ) {
|
||||
hintsMap.put( hint.name(), hint.value() );
|
||||
}
|
||||
|
@ -42,31 +46,74 @@ public class QueryHintDefinition {
|
|||
}
|
||||
|
||||
|
||||
public CacheMode getCacheMode(String query) {
|
||||
String hitName = QueryHints.CACHE_MODE;
|
||||
String value =(String) hintsMap.get( hitName );
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Generic access
|
||||
|
||||
public Map<String, Object> getHintsMap() {
|
||||
return hintsMap;
|
||||
}
|
||||
|
||||
public String getString(String hintName) {
|
||||
return (String) hintsMap.get( hintName );
|
||||
}
|
||||
|
||||
public boolean getBoolean(String hintName) {
|
||||
try {
|
||||
return CacheMode.interpretExternalSetting( value );
|
||||
return ConfigurationHelper.getBoolean( hintName, hintsMap );
|
||||
}
|
||||
catch ( MappingException e ) {
|
||||
throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + hitName, e );
|
||||
catch (Exception e) {
|
||||
throw new AnnotationException( "Named query hint [" + hintName + "] is not a boolean: " + queryName, e );
|
||||
}
|
||||
}
|
||||
|
||||
public FlushMode getFlushMode(String query) {
|
||||
String hitName = QueryHints.FLUSH_MODE;
|
||||
String value =(String) hintsMap.get( hitName );
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
public Integer getInteger(String hintName) {
|
||||
try {
|
||||
return FlushMode.interpretExternalSetting( value );
|
||||
return ConfigurationHelper.getInteger( hintName, hintsMap );
|
||||
}
|
||||
catch ( MappingException e ) {
|
||||
throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + hitName, e );
|
||||
catch (Exception e) {
|
||||
throw new AnnotationException( "Named query hint [" + hintName + "] is not an integer: " + queryName, e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Specialized access
|
||||
|
||||
public Integer getTimeout() {
|
||||
final Integer jpaTimeout = getInteger( QueryHints.TIMEOUT_JPA );
|
||||
if ( jpaTimeout != null ) {
|
||||
// convert milliseconds to seconds
|
||||
return (int) Math.round( jpaTimeout.doubleValue() / 1000.0 );
|
||||
}
|
||||
|
||||
return getInteger( QueryHints.TIMEOUT_HIBERNATE );
|
||||
}
|
||||
|
||||
public boolean getCacheability() {
|
||||
return getBoolean( QueryHints.CACHEABLE );
|
||||
}
|
||||
|
||||
public CacheMode getCacheMode() {
|
||||
final String value = getString( QueryHints.CACHE_MODE );
|
||||
try {
|
||||
return value == null
|
||||
? null
|
||||
: CacheMode.interpretExternalSetting( value );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new AnnotationException( "Unable to interpret CacheMode in named query hint: " + queryName, e );
|
||||
}
|
||||
}
|
||||
|
||||
public FlushMode getFlushMode() {
|
||||
final String value = getString( QueryHints.FLUSH_MODE );
|
||||
try {
|
||||
return value == null
|
||||
? null
|
||||
: FlushMode.interpretExternalSetting( value );
|
||||
}
|
||||
catch (MappingException e) {
|
||||
throw new AnnotationException( "Unable to interpret FlushMode in named query hint: " + queryName, e );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,58 +131,10 @@ public class QueryHintDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean getBoolean(String query, String hintName) {
|
||||
String value =(String) hintsMap.get( hintName );
|
||||
if ( value == null ) {
|
||||
return false;
|
||||
}
|
||||
if ( value.equalsIgnoreCase( "true" ) ) {
|
||||
return true;
|
||||
}
|
||||
else if ( value.equalsIgnoreCase( "false" ) ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
throw new AnnotationException( "Not a boolean in hint: " + query + ":" + hintName );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getString(String query, String hintName) {
|
||||
return (String) hintsMap.get( hintName );
|
||||
}
|
||||
|
||||
public Integer getInteger(String query, String hintName) {
|
||||
String value = (String) hintsMap.get( hintName );
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Integer.decode( value );
|
||||
}
|
||||
catch ( NumberFormatException nfe ) {
|
||||
throw new AnnotationException( "Not an integer in hint: " + query + ":" + hintName, nfe );
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getTimeout(String queryName) {
|
||||
Integer timeout = getInteger( queryName, QueryHints.TIMEOUT_JPA );
|
||||
|
||||
if ( timeout != null ) {
|
||||
// convert milliseconds to seconds
|
||||
timeout = (int) Math.round( timeout.doubleValue() / 1000.0 );
|
||||
}
|
||||
else {
|
||||
// timeout is already in seconds
|
||||
timeout = getInteger( queryName, QueryHints.TIMEOUT_HIBERNATE );
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public LockOptions determineLockOptions(NamedQuery namedQueryAnnotation) {
|
||||
LockModeType lockModeType = namedQueryAnnotation.lockMode();
|
||||
Integer lockTimeoutHint = getInteger( namedQueryAnnotation.name(), "javax.persistence.lock.timeout" );
|
||||
Boolean followOnLocking = getBoolean( namedQueryAnnotation.name(), QueryHints.FOLLOW_ON_LOCKING );
|
||||
Integer lockTimeoutHint = getInteger( "javax.persistence.lock.timeout" );
|
||||
Boolean followOnLocking = getBoolean( QueryHints.FOLLOW_ON_LOCKING );
|
||||
|
||||
return determineLockOptions(lockModeType, lockTimeoutHint, followOnLocking);
|
||||
}
|
||||
|
@ -150,8 +149,4 @@ public class QueryHintDefinition {
|
|||
|
||||
return lockOptions;
|
||||
}
|
||||
|
||||
public Map<String, Object> getHintsMap() {
|
||||
return hintsMap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.engine.spi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
|
||||
import org.hibernate.query.sql.internal.NamedNativeQueryMementoImpl;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
|
||||
public class NamedQueryDefinitionBuilder {
|
||||
protected String name;
|
||||
protected String query;
|
||||
protected boolean cacheable;
|
||||
protected String cacheRegion;
|
||||
protected Integer timeout;
|
||||
protected Integer fetchSize;
|
||||
protected FlushMode flushMode;
|
||||
protected CacheMode cacheMode;
|
||||
protected boolean readOnly;
|
||||
protected String comment;
|
||||
protected Map parameterTypes;
|
||||
protected LockOptions lockOptions;
|
||||
protected Integer firstResult;
|
||||
protected Integer maxResults;
|
||||
|
||||
public NamedQueryDefinitionBuilder() {
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setQuery(String query) {
|
||||
this.query = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setCacheable(boolean cacheable) {
|
||||
this.cacheable = cacheable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setCacheRegion(String cacheRegion) {
|
||||
this.cacheRegion = cacheRegion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setTimeout(Integer timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setFetchSize(Integer fetchSize) {
|
||||
this.fetchSize = fetchSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setFlushMode(FlushMode flushMode) {
|
||||
this.flushMode = flushMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setCacheMode(CacheMode cacheMode) {
|
||||
this.cacheMode = cacheMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setComment(String comment) {
|
||||
this.comment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder addParameterType(String name, String typeName) {
|
||||
if ( this.parameterTypes == null ) {
|
||||
this.parameterTypes = new HashMap();
|
||||
}
|
||||
this.parameterTypes.put( name, typeName );
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setParameterTypes(Map parameterTypes) {
|
||||
this.parameterTypes = parameterTypes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setLockOptions(LockOptions lockOptions) {
|
||||
this.lockOptions = lockOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setFirstResult(Integer firstResult) {
|
||||
this.firstResult = firstResult;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedQueryDefinitionBuilder setMaxResults(Integer maxResults) {
|
||||
this.maxResults = maxResults;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedNativeQueryMemento createNamedQueryDefinition() {
|
||||
return new NamedNativeQueryMementoImpl(
|
||||
name,
|
||||
query,
|
||||
cacheable,
|
||||
cacheRegion,
|
||||
timeout,
|
||||
lockOptions,
|
||||
fetchSize,
|
||||
flushMode,
|
||||
cacheMode,
|
||||
readOnly,
|
||||
comment,
|
||||
parameterTypes,
|
||||
firstResult,
|
||||
maxResults
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,182 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.engine.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.query.spi.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
|
||||
public class NamedSQLQueryDefinitionBuilder extends NamedQueryDefinitionBuilder {
|
||||
private NativeSQLQueryReturn[] queryReturns;
|
||||
private Collection<String> querySpaces;
|
||||
private boolean callable;
|
||||
private String resultSetRef;
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder() {
|
||||
}
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder(String name) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder setQueryReturns(NativeSQLQueryReturn[] queryReturns) {
|
||||
this.queryReturns = queryReturns;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder setQueryReturns(List<NativeSQLQueryReturn> queryReturns) {
|
||||
if ( queryReturns != null ) {
|
||||
this.queryReturns = queryReturns.toArray( new NativeSQLQueryReturn[ queryReturns.size() ] );
|
||||
}
|
||||
else {
|
||||
this.queryReturns = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder setQuerySpaces(List<String> querySpaces) {
|
||||
this.querySpaces = querySpaces;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder setQuerySpaces(Collection<String> synchronizedQuerySpaces) {
|
||||
this.querySpaces = synchronizedQuerySpaces;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder addSynchronizedQuerySpace(String table) {
|
||||
if ( this.querySpaces == null ) {
|
||||
this.querySpaces = new ArrayList<String>();
|
||||
}
|
||||
this.querySpaces.add( table );
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder setResultSetRef(String resultSetRef) {
|
||||
this.resultSetRef = resultSetRef;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedSQLQueryDefinitionBuilder setCallable(boolean callable) {
|
||||
this.callable = callable;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setName(String name) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setName( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setQuery(String query) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setQuery( query );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setCacheable(boolean cacheable) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setCacheable( cacheable );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setCacheRegion(String cacheRegion) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setCacheRegion( cacheRegion );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setTimeout(Integer timeout) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setTimeout( timeout );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setFetchSize(Integer fetchSize) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setFetchSize( fetchSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setFlushMode(FlushMode flushMode) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setFlushMode( flushMode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setCacheMode(CacheMode cacheMode) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setCacheMode( cacheMode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setReadOnly(boolean readOnly) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setReadOnly( readOnly );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setComment(String comment) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setComment( comment );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder addParameterType(String name, String typeName) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.addParameterType( name, typeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setParameterTypes(Map parameterTypes) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setParameterTypes( parameterTypes );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setLockOptions(LockOptions lockOptions) {
|
||||
// todo : maybe throw an exception here instead? since this is not valid for native-0sql queries?
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setLockOptions( lockOptions );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setFirstResult(Integer firstResult) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setFirstResult( firstResult );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedSQLQueryDefinitionBuilder setMaxResults(Integer maxResults) {
|
||||
return (NamedSQLQueryDefinitionBuilder) super.setMaxResults( maxResults );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamedNativeQueryMemento createNamedQueryDefinition() {
|
||||
return new NamedSQLQueryDefinition(
|
||||
name,
|
||||
query,
|
||||
cacheable,
|
||||
cacheRegion,
|
||||
timeout,
|
||||
fetchSize,
|
||||
flushMode,
|
||||
cacheMode,
|
||||
readOnly,
|
||||
comment,
|
||||
parameterTypes,
|
||||
firstResult,
|
||||
maxResults,
|
||||
resultSetRef,
|
||||
querySpacesCopy(),
|
||||
callable,
|
||||
queryReturns
|
||||
);
|
||||
}
|
||||
|
||||
private List<String> querySpacesCopy() {
|
||||
return querySpaces == null
|
||||
? null
|
||||
: new ArrayList<String>( querySpaces );
|
||||
}
|
||||
}
|
|
@ -69,7 +69,7 @@ import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
|
|||
import org.hibernate.jpa.spi.TupleBuilderTransformer;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.internal.ProcedureCallImpl;
|
||||
import org.hibernate.query.ParameterMetadata;
|
||||
import org.hibernate.query.Query;
|
||||
|
|
|
@ -73,12 +73,12 @@ import org.hibernate.engine.jndi.spi.JndiService;
|
|||
import org.hibernate.engine.profile.Association;
|
||||
import org.hibernate.engine.profile.Fetch;
|
||||
import org.hibernate.engine.profile.FetchProfile;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
import org.hibernate.query.spi.QueryPlanCache;
|
||||
import org.hibernate.engine.query.spi.ReturnMetadata;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
|
||||
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
|
||||
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
|
||||
import org.hibernate.boot.spi.NamedNativeQueryMementoBuilder;
|
||||
import org.hibernate.engine.spi.SessionBuilderImplementor;
|
||||
import org.hibernate.engine.spi.SessionEventListenerManager;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -894,8 +894,8 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
);
|
||||
}
|
||||
|
||||
private NamedSQLQueryDefinition extractSqlQueryDefinition(NativeQuery nativeSqlQuery, String name) {
|
||||
final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder( name );
|
||||
private NamedSQLQueryDefinition extractSqlQueryDefinition(org.hibernate.query.NativeQuery nativeSqlQuery, String name) {
|
||||
final NamedNativeQueryMementoBuilder builder = new NamedNativeQueryMementoBuilder( name );
|
||||
fillInNamedQueryBuilder( builder, nativeSqlQuery );
|
||||
builder.setCallable( nativeSqlQuery.isCallable() )
|
||||
.setQuerySpaces( nativeSqlQuery.getSynchronizedQuerySpaces() )
|
||||
|
@ -904,14 +904,14 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
|||
}
|
||||
|
||||
private NamedHqlQueryMementoImpl extractHqlQueryDefinition(org.hibernate.query.Query hqlQuery, String name) {
|
||||
final NamedQueryDefinitionBuilder builder = new NamedQueryDefinitionBuilder( name );
|
||||
final NamedHqlQueryMemento.Builder builder = new NamedHqlQueryMemento.Builder( name );
|
||||
fillInNamedQueryBuilder( builder, hqlQuery );
|
||||
// LockOptions only valid for HQL/JPQL queries...
|
||||
builder.setLockOptions( hqlQuery.getLockOptions().makeCopy() );
|
||||
return builder.createNamedQueryDefinition();
|
||||
}
|
||||
|
||||
private void fillInNamedQueryBuilder(NamedQueryDefinitionBuilder builder, org.hibernate.query.Query query) {
|
||||
private void fillInNamedQueryBuilder(NamedHqlQueryMemento.Builder builder, org.hibernate.query.Query query) {
|
||||
builder.setQuery( query.getQueryString() )
|
||||
.setComment( query.getComment() )
|
||||
.setCacheable( query.isCacheable() )
|
||||
|
|
|
@ -158,7 +158,7 @@ import org.hibernate.persister.entity.MultiLoadOptions;
|
|||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.UnknownSqlResultSetMappingException;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.procedure;
|
|||
import javax.persistence.ParameterMode;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.query.procedure.ProcedureParameter;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -72,8 +71,11 @@ public interface ParameterRegistration<T> extends ProcedureParameter<T> {
|
|||
* The (global) default this setting is defined by {@link org.hibernate.cfg.AvailableSettings#PROCEDURE_NULL_PARAM_PASSING}
|
||||
*
|
||||
* @param enabled {@code true} indicates that the NULL should be passed; {@code false} indicates it should not.
|
||||
*
|
||||
* @deprecated (since 6.0) : see {@link #isPassNullsEnabled}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
void enablePassingNulls(boolean enabled);
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,6 +14,7 @@ import javax.persistence.StoredProcedureQuery;
|
|||
import org.hibernate.BasicQueryContract;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.SynchronizeableQuery;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.query.CommonQueryContract;
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,53 +11,73 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
|
||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
||||
import org.hibernate.query.QueryParameter;
|
||||
import org.hibernate.query.spi.AbstractNamedQueryMemento;
|
||||
import org.hibernate.query.spi.ParameterMemento;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Implementation of ProcedureCallMemento
|
||||
* Implementation of NamedCallableQueryMemento
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento {
|
||||
private final String procedureName;
|
||||
private final NativeSQLQueryReturn[] queryReturns;
|
||||
|
||||
public class NamedCallableQueryMementoImpl extends AbstractNamedQueryMemento implements NamedCallableQueryMemento {
|
||||
private final String callableName;
|
||||
private final ParameterStrategy parameterStrategy;
|
||||
private final List<ParameterMemento> parameterDeclarations;
|
||||
private final Class[] resultClasses;
|
||||
private final String[] resultSetMappingNames;
|
||||
private final Set<String> querySpaces;
|
||||
|
||||
private final Set<String> synchronizedQuerySpaces;
|
||||
|
||||
private final Map<String, Object> hintsMap;
|
||||
|
||||
/**
|
||||
* Constructs a ProcedureCallImpl
|
||||
*
|
||||
* @param procedureName The name of the procedure to be called
|
||||
* @param queryReturns The result mappings
|
||||
* @param parameterStrategy Are parameters named or positional?
|
||||
* @param parameterDeclarations The parameters registrations
|
||||
* @param synchronizedQuerySpaces Any query spaces to synchronize on execution
|
||||
* @param hintsMap Map of JPA query hints
|
||||
*/
|
||||
public NamedCallableQueryMementoImpl(
|
||||
String procedureName,
|
||||
NativeSQLQueryReturn[] queryReturns,
|
||||
String name,
|
||||
String callableName,
|
||||
ParameterStrategy parameterStrategy,
|
||||
List<ParameterMemento> parameterDeclarations,
|
||||
Set<String> synchronizedQuerySpaces,
|
||||
Map<String, Object> hintsMap) {
|
||||
this.procedureName = procedureName;
|
||||
this.queryReturns = queryReturns;
|
||||
List<CallableParameterMemento> parameterMementos,
|
||||
Class[] resultClasses,
|
||||
String[] resultSetMappingNames,
|
||||
Set<String> querySpaces,
|
||||
Boolean cacheable,
|
||||
String cacheRegion,
|
||||
CacheMode cacheMode,
|
||||
FlushMode flushMode,
|
||||
Boolean readOnly,
|
||||
LockOptions lockOptions,
|
||||
Integer timeout,
|
||||
Integer fetchSize,
|
||||
String comment,
|
||||
Map<String, Object> hints) {
|
||||
super(
|
||||
name,
|
||||
parameterMementos,
|
||||
cacheable,
|
||||
cacheRegion,
|
||||
cacheMode,
|
||||
flushMode,
|
||||
readOnly,
|
||||
lockOptions,
|
||||
timeout,
|
||||
fetchSize,
|
||||
comment,
|
||||
hints
|
||||
);
|
||||
this.callableName = callableName;
|
||||
this.parameterStrategy = parameterStrategy;
|
||||
this.parameterDeclarations = parameterDeclarations;
|
||||
this.synchronizedQuerySpaces = synchronizedQuerySpaces;
|
||||
this.hintsMap = hintsMap;
|
||||
this.resultClasses = resultClasses;
|
||||
this.resultSetMappingNames = resultSetMappingNames;
|
||||
this.querySpaces = querySpaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,8 +85,8 @@ public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento
|
|||
return new ProcedureCallImpl( session, this );
|
||||
}
|
||||
|
||||
public String getProcedureName() {
|
||||
return procedureName;
|
||||
public String getCallableName() {
|
||||
return callableName;
|
||||
}
|
||||
|
||||
public NativeSQLQueryReturn[] getQueryReturns() {
|
||||
|
@ -93,7 +113,7 @@ public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento
|
|||
/**
|
||||
* A "disconnected" copy of the metadata for a parameter, that can be used in ProcedureCallMementoImpl.
|
||||
*/
|
||||
public static class ParameterMemento {
|
||||
public static class CallableParameterMemento implements ParameterMemento {
|
||||
private final Integer position;
|
||||
private final String name;
|
||||
private final ParameterMode mode;
|
||||
|
@ -111,7 +131,7 @@ public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento
|
|||
* @param hibernateType The Hibernate Type.
|
||||
* @param passNulls Should NULL values to passed to the database?
|
||||
*/
|
||||
public ParameterMemento(
|
||||
public CallableParameterMemento(
|
||||
int position,
|
||||
String name,
|
||||
ParameterMode mode,
|
||||
|
@ -150,6 +170,11 @@ public class NamedCallableQueryMementoImpl implements NamedCallableQueryMemento
|
|||
return passNulls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryParameter toQueryParameter(SharedSessionContractImplementor session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a ParameterMemento from the given parameter registration
|
||||
*
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.hibernate.procedure.NoSuchParameterException;
|
|||
import org.hibernate.procedure.ParameterRegistration;
|
||||
import org.hibernate.procedure.ParameterStrategyException;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.ProcedureOutputs;
|
||||
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
|
||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.procedure;
|
||||
package org.hibernate.procedure.spi;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -12,6 +12,8 @@ import org.hibernate.Incubating;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.query.spi.NamedQueryMemento;
|
||||
|
||||
/**
|
||||
* Represents a "memento" (disconnected, externalizable form) of a ProcedureCall
|
||||
|
@ -19,7 +21,20 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface NamedCallableQueryMemento {
|
||||
public interface NamedCallableQueryMemento extends NamedQueryMemento {
|
||||
@Override
|
||||
default String getQueryString() {
|
||||
return getCallableName();
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the database callable to execute. Whereas {@link #getName()}
|
||||
* describes the name under which the named query is registered with the
|
||||
* SessionFactory, the callable name is the actual database procedure/function
|
||||
* name
|
||||
*/
|
||||
String getCallableName();
|
||||
|
||||
/**
|
||||
* Convert the memento back into an executable (connected) form.
|
||||
*
|
|
@ -9,7 +9,6 @@ package org.hibernate.query;
|
|||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.DotIdentifierSequence;
|
||||
import org.hibernate.internal.util.Loggable;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
|
||||
|
@ -21,7 +20,7 @@ import org.hibernate.metamodel.model.domain.NavigableRole;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NavigablePath implements DotIdentifierSequence, Loggable {
|
||||
public class NavigablePath implements DotIdentifierSequence {
|
||||
public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper";
|
||||
|
||||
private final NavigablePath parent;
|
||||
|
|
|
@ -4,11 +4,8 @@
|
|||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
|
||||
package org.hibernate.query;
|
||||
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
|
||||
|
@ -21,18 +18,6 @@ import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
|||
*/
|
||||
@Incubating
|
||||
public interface QueryParameter<T> extends javax.persistence.Parameter<T> {
|
||||
/**
|
||||
* Is this a {@code IN}, {@code OUT} or {@code INOUT} parameter.
|
||||
* <p/>
|
||||
* Only really pertinent in regards to procedure/function calls. In all
|
||||
* other cases the mode would be {@link ParameterMode#IN}
|
||||
*
|
||||
* @return The parameter mode.
|
||||
*/
|
||||
default ParameterMode getMode() {
|
||||
return ParameterMode.IN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this parameter allow multi-valued (collection, array, etc) binding?
|
||||
* <p/>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.sqm.produce;
|
||||
package org.hibernate.query.hql;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
|
@ -14,12 +14,12 @@ import org.hibernate.HibernateException;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmProductionException extends HibernateException {
|
||||
public SqmProductionException(String message) {
|
||||
public class HqlInterpretationException extends HibernateException {
|
||||
public HqlInterpretationException(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
public SqmProductionException(String message, Throwable cause) {
|
||||
public HqlInterpretationException(String message, Throwable cause) {
|
||||
super( message, cause );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class FullyQualifiedReflectivePath implements SemanticPathPart, FullyQualifiedReflectivePathSource {
|
||||
private final FullyQualifiedReflectivePathSource pathSource;
|
||||
private final String localName;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public FullyQualifiedReflectivePath(
|
||||
FullyQualifiedReflectivePathSource pathSource,
|
||||
String localName) {
|
||||
this.pathSource = pathSource;
|
||||
this.localName = localName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullyQualifiedReflectivePath resolvePathPart(
|
||||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
if ( isTerminal ) {
|
||||
return new FullyQualifiedReflectivePathTerminal( this, name, creationState );
|
||||
}
|
||||
else {
|
||||
return new FullyQualifiedReflectivePath( this, name );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<?> resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new UnsupportedOperationException( "Fully qualified reflective paths cannot contain indexed access" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullyQualifiedReflectivePathSource getParent() {
|
||||
return pathSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalName() {
|
||||
return localName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullPath() {
|
||||
return pathSource.getFullPath() + '.' + localName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullyQualifiedReflectivePath append(String subPathName) {
|
||||
return new FullyQualifiedReflectivePath( this, subPathName );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import org.hibernate.DotIdentifierSequence;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public interface FullyQualifiedReflectivePathSource extends DotIdentifierSequence, SemanticPathPart {
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.persistence.criteria.Expression;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.hql.HqlInterpretationException;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class FullyQualifiedReflectivePathTerminal
|
||||
extends FullyQualifiedReflectivePath
|
||||
implements SqmExpression {
|
||||
private final SqmExpressable expressableType;
|
||||
private final SqmCreationState creationState;
|
||||
|
||||
private final Function<SemanticQueryWalker,?> handler;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public FullyQualifiedReflectivePathTerminal(
|
||||
FullyQualifiedReflectivePathSource pathSource,
|
||||
String subPathName,
|
||||
SqmCreationState creationState) {
|
||||
super( pathSource, subPathName );
|
||||
this.creationState = creationState;
|
||||
|
||||
this.handler = resolveTerminalSemantic();
|
||||
|
||||
// todo (6.0) : how to calculate this?
|
||||
this.expressableType = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Function<SemanticQueryWalker, ?> resolveTerminalSemantic() {
|
||||
return semanticQueryWalker -> {
|
||||
final ClassLoaderService cls = creationState.getCreationContext().getServiceRegistry().getService( ClassLoaderService.class );
|
||||
final String fullPath = getFullPath();
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// See if it is an entity-type literal
|
||||
|
||||
final EntityDomainType<?> entityDescriptor = creationState.getCreationContext().getJpaMetamodel().entity( fullPath );
|
||||
if ( entityDescriptor != null ) {
|
||||
return new SqmLiteralEntityType( entityDescriptor, creationState.getCreationContext().getNodeBuilder() );
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// See if it is a Class FQN
|
||||
|
||||
try {
|
||||
final Class namedClass = cls.classForName( fullPath );
|
||||
if ( namedClass != null ) {
|
||||
return semanticQueryWalker.visitFullyQualifiedClass( namedClass );
|
||||
}
|
||||
}
|
||||
catch (ClassLoadingException ignore) {
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Check the parent path as a Class FQN, meaning the terminal is a field or
|
||||
// enum-value
|
||||
|
||||
final String parentFullPath = getParent().getFullPath();
|
||||
try {
|
||||
final Class namedClass = cls.classForName( parentFullPath );
|
||||
if ( namedClass != null ) {
|
||||
if ( namedClass.isEnum() ) {
|
||||
return semanticQueryWalker.visitFullyQualifiedEnum(
|
||||
Enum.valueOf( namedClass, getLocalName() )
|
||||
);
|
||||
}
|
||||
else {
|
||||
final Field field = namedClass.getField( getLocalName() );
|
||||
return semanticQueryWalker.visitFullyQualifiedField( field );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ClassLoadingException | NoSuchFieldException ignore) {
|
||||
}
|
||||
|
||||
throw new HqlInterpretationException( "Unsure how to handle semantic path terminal - " + fullPath );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable getNodeType() {
|
||||
return expressableType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object accept(SemanticQueryWalker walker) {
|
||||
return handler.apply( walker );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||
return expressableType.getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applyInferableType(SqmExpressable type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Long> asLong() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Integer> asInteger() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Float> asFloat() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Double> asDouble() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<BigDecimal> asBigDecimal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<BigInteger> asBigInteger() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<String> asString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression as(Class type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate isNull() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate isNotNull() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Object... values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Expression[] values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Collection values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Expression values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends JpaSelection<?>> getSelectionItems() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaSelection alias(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompoundSelection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlias() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeBuilder nodeBuilder() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -21,8 +21,10 @@ import org.hibernate.query.spi.ParameterMemento;
|
|||
import org.hibernate.query.sqm.internal.QuerySqmImpl;
|
||||
|
||||
/**
|
||||
* Definition of a named query, defined in the mapping metadata. Additional, as of JPA 2.1, named query definition
|
||||
* can also come from a compiled query.
|
||||
* Definition of a named query, defined in the mapping metadata.
|
||||
*
|
||||
* Additionally, as of JPA 2.1, named query definition can also come
|
||||
* from a compiled query.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
|
@ -34,8 +36,8 @@ public class NamedHqlQueryMementoImpl extends AbstractNamedQueryMemento implemen
|
|||
|
||||
public NamedHqlQueryMementoImpl(
|
||||
String name,
|
||||
List<ParameterMemento> parameterMementos,
|
||||
String hqlString,
|
||||
List<ParameterMemento> parameterMementos,
|
||||
Integer firstResult,
|
||||
Integer maxResults,
|
||||
Boolean cacheable,
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationContext;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.type.descriptor.java.spi.EnumJavaDescriptor;
|
||||
|
||||
/**
|
||||
* A delayed resolution of a non-terminal path part
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SemanticPathPartDelayedResolution implements SemanticPathPart, FullyQualifiedReflectivePathSource {
|
||||
private final FullyQualifiedReflectivePathSource parent;
|
||||
|
||||
// todo (6.0) : consider reusing this PossiblePackageRoot instance, updating the state fields
|
||||
// - we'd still add to the stack, but we'd save the instantiations
|
||||
|
||||
private final String fullPath;
|
||||
private final String localName;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public SemanticPathPartDelayedResolution(String name) {
|
||||
this( null, name );
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public SemanticPathPartDelayedResolution(
|
||||
FullyQualifiedReflectivePathSource parent,
|
||||
String localName) {
|
||||
this.parent = parent;
|
||||
this.localName = localName;
|
||||
|
||||
this.fullPath = parent == null ? localName : parent.append( localName ).getFullPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullyQualifiedReflectivePathSource getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalName() {
|
||||
return localName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullPath() {
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemanticPathPartDelayedResolution append(String subPathName) {
|
||||
throw new UnsupportedOperationException( "Use #resolvePathPart instead" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String subName,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
final String combinedName = this.fullPath + '.' + subName;
|
||||
|
||||
final SqmCreationContext creationContext = creationState.getCreationContext();
|
||||
|
||||
if ( isTerminal ) {
|
||||
final EntityDomainType entityTypeByName = creationContext.getJpaMetamodel().entity( combinedName );
|
||||
if ( entityTypeByName != null ) {
|
||||
//noinspection unchecked
|
||||
return new SqmLiteralEntityType( entityTypeByName, creationContext.getNodeBuilder() );
|
||||
}
|
||||
|
||||
// the incoming subName could be a field or enum reference relative to this combinedName
|
||||
// which would mean the combinedName must be a class name
|
||||
final ClassLoaderService classLoaderService = creationContext
|
||||
.getServiceRegistry()
|
||||
.getService( ClassLoaderService.class );
|
||||
|
||||
// todo (6.0) : would be nice to leverage imported names here
|
||||
try {
|
||||
final Class referencedClass = classLoaderService.classForName( combinedName );
|
||||
|
||||
if ( referencedClass.isEnum() ) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
final Enum<?> enumValue = Enum.valueOf( referencedClass, subName );
|
||||
//noinspection unchecked
|
||||
return new SqmEnumLiteral(
|
||||
enumValue,
|
||||
(EnumJavaDescriptor) creationContext.getJpaMetamodel()
|
||||
.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.resolveDescriptor( referencedClass ),
|
||||
subName,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore - it could still potentially be a static field reference
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final Field field = referencedClass.getDeclaredField( subName );
|
||||
//noinspection unchecked
|
||||
return new SqmFieldLiteral<>(
|
||||
field.get( null ),
|
||||
creationContext.getJpaMetamodel()
|
||||
.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
.resolveDescriptor( referencedClass ),
|
||||
subName,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore - fall through to the exception below
|
||||
}
|
||||
}
|
||||
catch (ClassLoadingException e) {
|
||||
// ignore - we will hit the exception below
|
||||
}
|
||||
|
||||
throw new SemanticException( "Could not resolve path terminal : " + combinedName + '.' + subName );
|
||||
}
|
||||
else {
|
||||
|
||||
return new SemanticPathPartDelayedResolution( this, subName );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<?> resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SemanticPathPartJoinPredicate implements SemanticPathPart {
|
||||
private final SqmFrom joinLhs;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public SemanticPathPartJoinPredicate(SqmFrom joinLhs) {
|
||||
super();
|
||||
this.joinLhs = joinLhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
final SqmCreationProcessingState processingState = creationState.getCurrentProcessingState();
|
||||
final SqmPathRegistry pathRegistry = processingState.getPathRegistry();
|
||||
|
||||
// #1 - name is joinLhs alias
|
||||
if ( name.equals( joinLhs.getExplicitAlias() ) ) {
|
||||
return joinLhs;
|
||||
}
|
||||
|
||||
// #2 - name is alias for another SqmFrom
|
||||
final SqmFrom fromByAlias = pathRegistry.findFromByAlias( name );
|
||||
if ( fromByAlias != null ) {
|
||||
validatePathRoot( fromByAlias );
|
||||
return fromByAlias;
|
||||
}
|
||||
|
||||
// #3 - name is a unqualified attribute reference relative to the current processing state
|
||||
final SqmFrom fromExposing = pathRegistry.findFromExposing( name );
|
||||
if ( fromExposing != null ) {
|
||||
validatePathRoot( fromExposing );
|
||||
return fromExposing;
|
||||
}
|
||||
|
||||
if ( ! isTerminal ) {
|
||||
return new SemanticPathPartDelayedResolution( name );
|
||||
}
|
||||
|
||||
throw new SemanticException( "Could not resolve path root used in join predicate: " + name );
|
||||
}
|
||||
|
||||
private void validatePathRoot(SqmPath path) {
|
||||
if ( ! path.findRoot().equals( joinLhs.findRoot() ) ) {
|
||||
throw new SemanticException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Qualified join predicate path [%s] referred to from-clause root other that the join rhs",
|
||||
path.getNavigablePath().getFullPath()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException( "Illegal index-access as join predicate root" );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.SqmJoinable;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
||||
/**
|
||||
* SemanticPathPart handling specific to processing a qualified join path
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SemanticPathPartQualifiedJoinPath implements SemanticPathPart {
|
||||
private final SqmRoot sqmRoot;
|
||||
|
||||
private final SqmJoinType joinType;
|
||||
private final boolean fetch;
|
||||
private final String alias;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public SemanticPathPartQualifiedJoinPath(SqmRoot sqmRoot, SqmJoinType joinType, boolean fetch, String alias) {
|
||||
this.sqmRoot = sqmRoot;
|
||||
this.joinType = joinType;
|
||||
this.fetch = fetch;
|
||||
this.alias = alias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
final SqmCreationProcessingState processingState = creationState.getCurrentProcessingState();
|
||||
final SqmPathRegistry pathRegistry = processingState.getPathRegistry();
|
||||
|
||||
final SqmFrom fromByAlias = pathRegistry.findFromByAlias( name );
|
||||
if ( fromByAlias != null ) {
|
||||
return fromByAlias;
|
||||
}
|
||||
|
||||
final SqmFrom fromExposing = pathRegistry.findFromExposing( name );
|
||||
if ( fromExposing != null ) {
|
||||
final SqmAttributeJoin join = ( (SqmJoinable) fromExposing.getReferencedPathSource().findSubPathSource(
|
||||
name ) ).createSqmJoin(
|
||||
fromExposing,
|
||||
joinType,
|
||||
isTerminal ? alias : null,
|
||||
fetch,
|
||||
creationState
|
||||
);
|
||||
pathRegistry.register( join );
|
||||
return join;
|
||||
}
|
||||
|
||||
// otherwise it has to be an entity join
|
||||
|
||||
if ( isTerminal ) {
|
||||
final EntityDomainType<?> entityType = processingState.getCreationState()
|
||||
.getCreationContext()
|
||||
.getJpaMetamodel()
|
||||
.entity( name );
|
||||
if ( entityType == null ) {
|
||||
throw new SemanticException( "Could not resolve qualified join path: " + name );
|
||||
}
|
||||
final SqmEntityJoin<?> entityJoin = new SqmEntityJoin<>( entityType, alias, joinType, sqmRoot );
|
||||
pathRegistry.register( entityJoin );
|
||||
return entityJoin;
|
||||
}
|
||||
|
||||
return new SemanticPathPartDelayedEntityJoinHandler( name, sqmRoot, joinType, alias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException( "Illegal index-access as qualified join path" );
|
||||
}
|
||||
|
||||
private static class SemanticPathPartDelayedEntityJoinHandler implements SemanticPathPart {
|
||||
private final SqmRoot sqmRoot;
|
||||
|
||||
private final SqmJoinType joinType;
|
||||
private final String alias;
|
||||
|
||||
private String pathSoFar;
|
||||
|
||||
private SemanticPathPartDelayedEntityJoinHandler(
|
||||
String baseName,
|
||||
SqmRoot sqmRoot,
|
||||
SqmJoinType joinType,
|
||||
String alias) {
|
||||
this.sqmRoot = sqmRoot;
|
||||
this.joinType = joinType;
|
||||
this.alias = alias;
|
||||
|
||||
this.pathSoFar = baseName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
pathSoFar = pathSoFar + '.' + name;
|
||||
if ( ! isTerminal ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
final SqmCreationProcessingState processingState = creationState.getCurrentProcessingState();
|
||||
final SqmPathRegistry pathRegistry = processingState.getPathRegistry();
|
||||
|
||||
final EntityDomainType<?> entityType = processingState.getCreationState()
|
||||
.getCreationContext()
|
||||
.getJpaMetamodel()
|
||||
.entity( name );
|
||||
if ( entityType == null ) {
|
||||
throw new SemanticException( "Could not resolve qualified join path: " + name );
|
||||
}
|
||||
final SqmEntityJoin<?> entityJoin = new SqmEntityJoin<>( entityType, alias, joinType, sqmRoot );
|
||||
pathRegistry.register( entityJoin );
|
||||
|
||||
return entityJoin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException( "Illegal index-access as qualified join path" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationContext;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SemanticPathPartRoot implements SemanticPathPart {
|
||||
public SemanticPathPartRoot() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
// At this point we have a "root reference"... the first path part in
|
||||
// a potential series of path parts
|
||||
|
||||
final SqmPathRegistry pathRegistry = creationState.getProcessingStateStack().getCurrent().getPathRegistry();
|
||||
final SqmCreationContext creationContext = creationState.getCreationContext();
|
||||
|
||||
// this root reference could be any of:
|
||||
// 1) a from-element alias
|
||||
// 2) an unqualified attribute name exposed from one (and only one!) from-element
|
||||
// 3) an unqualified (imported) entity name
|
||||
|
||||
// #1
|
||||
final SqmFrom aliasedFromElement = pathRegistry.findFromByAlias( name );
|
||||
if ( aliasedFromElement != null ) {
|
||||
return aliasedFromElement;
|
||||
}
|
||||
|
||||
|
||||
// #2
|
||||
final SqmFrom unqualifiedAttributeOwner = pathRegistry.findFromExposing( name );
|
||||
if ( unqualifiedAttributeOwner != null ) {
|
||||
return unqualifiedAttributeOwner.resolvePathPart( name, false, creationState );
|
||||
}
|
||||
|
||||
// #3
|
||||
final EntityDomainType<?> entityTypeByName = creationContext.getJpaMetamodel().entity( name );
|
||||
if ( entityTypeByName != null ) {
|
||||
//noinspection unchecked
|
||||
return new SqmLiteralEntityType( entityTypeByName, creationState.getCreationContext().getNodeBuilder() );
|
||||
}
|
||||
|
||||
if ( ! isTerminal ) {
|
||||
return new SemanticPathPartDelayedResolution( name );
|
||||
}
|
||||
|
||||
throw new SemanticException( "Could not resolve path root : " + name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException( "Path cannot start with index-access" );
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.SortOrder;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
|
@ -38,7 +39,8 @@ import org.hibernate.query.QueryLogger;
|
|||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.TrimSpec;
|
||||
import org.hibernate.query.UnaryArithmeticOperator;
|
||||
import org.hibernate.query.hql.DotIdentifierConsumer;
|
||||
import org.hibernate.query.hql.HqlInterpretationException;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.LiteralNumberFormatException;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.ParsingException;
|
||||
|
@ -47,15 +49,12 @@ import org.hibernate.query.sqm.SqmPathSource;
|
|||
import org.hibernate.query.sqm.StrictJpaComplianceViolation;
|
||||
import org.hibernate.query.sqm.UnknownEntityException;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.SqmProductionException;
|
||||
import org.hibernate.query.sqm.produce.SqmQuerySpecCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.SqmTreeCreationLogger;
|
||||
import org.hibernate.query.sqm.produce.function.SqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.produce.function.spi.NamedSqmFunctionTemplate;
|
||||
import org.hibernate.query.sqm.produce.internal.SqmDmlCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
|
||||
import org.hibernate.query.sqm.produce.internal.UniqueIdGenerator;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.ImplicitAliasGenerator;
|
||||
import org.hibernate.query.sqm.produce.spi.ParameterDeclarationContext;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationContext;
|
||||
|
@ -93,7 +92,6 @@ import org.hibernate.query.sqm.tree.expression.function.SqmExtractUnit;
|
|||
import org.hibernate.query.sqm.tree.expression.function.SqmStar;
|
||||
import org.hibernate.query.sqm.tree.expression.function.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.from.DowncastLocation;
|
||||
import org.hibernate.query.sqm.tree.from.MutableUsageDetails;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
|
||||
|
@ -169,7 +167,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
private final ImplicitAliasGenerator implicitAliasGenerator;
|
||||
private final UniqueIdGenerator uidGenerator;
|
||||
|
||||
private final Stack<DotIdentifierConsumer> identifierConsumerStack;
|
||||
private final Stack<SemanticPathPart> semanticPathPartStack;
|
||||
|
||||
private final Stack<TreatHandler> treatHandlerStack = new StandardStack<>( new TreatHandlerNormal() );
|
||||
|
||||
|
@ -190,9 +188,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
this.implicitAliasGenerator = new ImplicitAliasGenerator();
|
||||
this.uidGenerator = new UniqueIdGenerator();
|
||||
|
||||
this.identifierConsumerStack = new StandardStack<>(
|
||||
new BasicDotIdentifierConsumer( processingStateStack::getCurrent )
|
||||
);
|
||||
this.semanticPathPartStack = new StandardStack<>( new SemanticPathPartRoot() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -205,37 +201,10 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
return creationOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImplicitAliasGenerator getImplicitAliasGenerator() {
|
||||
return implicitAliasGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateUniqueIdentifier() {
|
||||
return uidGenerator.generateUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmQuerySpecCreationProcessingState getCurrentQuerySpecProcessingState() {
|
||||
final SqmCreationProcessingState current = processingStateStack.getCurrent();
|
||||
if ( current instanceof SqmQuerySpecCreationProcessingState ) {
|
||||
return (SqmQuerySpecCreationProcessingState) current;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException( "Current processing state is not related to a SqmQuerySpec : " + current );
|
||||
}
|
||||
|
||||
protected <T> void primeStack(Stack<T> stack, T initialValue) {
|
||||
stack.push( initialValue );
|
||||
}
|
||||
|
||||
protected Stack<ParameterDeclarationContext> getParameterDeclarationContextStack() {
|
||||
return parameterDeclarationContextStack;
|
||||
}
|
||||
|
||||
protected Stack<DotIdentifierConsumer> getIdentifierConsumerStack() {
|
||||
return identifierConsumerStack;
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Grammar rules
|
||||
|
@ -322,13 +291,6 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
processingStateStack.push( new SqmDmlCreationProcessingState( insertStatement, this ) );
|
||||
|
||||
try {
|
||||
String alias = getImplicitAliasGenerator().generateUniqueImplicitAlias();
|
||||
log.debugf(
|
||||
"Generated implicit alias [%s] for INSERT target [%s]",
|
||||
alias,
|
||||
targetType.getHibernateEntityName()
|
||||
);
|
||||
|
||||
insertStatement.setSelectQuerySpec( visitQuerySpec( ctx.querySpec() ) );
|
||||
|
||||
for ( HqlParser.DotIdentifierSequenceContext stateFieldCtx : ctx.insertSpec().targetFieldsSpec().dotIdentifierSequence() ) {
|
||||
|
@ -498,9 +460,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
public SqmSelectClause visitSelectClause(HqlParser.SelectClauseContext ctx) {
|
||||
treatHandlerStack.push( new TreatHandlerNormal( DowncastLocation.SELECT ) );
|
||||
|
||||
identifierConsumerStack.push(
|
||||
new SelectClauseDotIdentifierConsumer( this::getCurrentQuerySpecProcessingState )
|
||||
);
|
||||
// todo (6.0) : primer a select-clause-specific SemanticPathPart into the stack
|
||||
|
||||
try {
|
||||
final SqmSelectClause selectClause = new SqmSelectClause(
|
||||
|
@ -513,7 +473,6 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
return selectClause;
|
||||
}
|
||||
finally {
|
||||
identifierConsumerStack.pop();
|
||||
treatHandlerStack.pop();
|
||||
}
|
||||
}
|
||||
|
@ -530,7 +489,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
creationContext.getNodeBuilder()
|
||||
);
|
||||
|
||||
getCurrentQuerySpecProcessingState().registerSelection( selection );
|
||||
getProcessingStateStack().getCurrent().getPathRegistry().register( selection );
|
||||
|
||||
return selection;
|
||||
}
|
||||
|
@ -737,7 +696,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
public SqmExpression visitSortExpression(HqlParser.SortExpressionContext ctx) {
|
||||
if ( ctx.INTEGER_LITERAL() != null ) {
|
||||
final int position = Integer.parseInt( ctx.INTEGER_LITERAL().getText() );
|
||||
final SqmSelection selection = getCurrentQuerySpecProcessingState().findSelectionByPosition( position );
|
||||
final SqmSelection selection = getCurrentProcessingState().getPathRegistry().findSelectionByPosition( position );
|
||||
if ( selection != null ) {
|
||||
final SqmSelectableNode selectableNode = selection.getSelectableNode();
|
||||
if ( selectableNode instanceof SqmExpression ) {
|
||||
|
@ -749,22 +708,13 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
}
|
||||
|
||||
if ( ctx.identifier() != null ) {
|
||||
final SqmSelection selection = getCurrentQuerySpecProcessingState().findSelectionByAlias( ctx.identifier().getText() );
|
||||
final SqmSelection selection = getCurrentProcessingState().getPathRegistry().findSelectionByAlias( ctx.identifier().getText() );
|
||||
if ( selection != null ) {
|
||||
final SqmSelectableNode selectableNode = selection.getSelectableNode();
|
||||
if ( selectableNode instanceof SqmExpression ) {
|
||||
return (SqmExpression) selectableNode;
|
||||
}
|
||||
}
|
||||
|
||||
final DotIdentifierConsumer dotIdentifierConsumer = identifierConsumerStack.getCurrent();
|
||||
dotIdentifierConsumer.consumeIdentifier(
|
||||
ctx.identifier().getText(),
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
return (SqmExpression) dotIdentifierConsumer.getConsumedPart();
|
||||
}
|
||||
|
||||
return (SqmExpression) ctx.expression().accept( this );
|
||||
|
@ -1012,15 +962,14 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
|
||||
final String alias = visitIdentificationVariableDef( parserJoin.qualifiedJoinRhs().identificationVariableDef() );
|
||||
|
||||
final DotIdentifierConsumer identifierConsumer = new QualifiedJoinPathIdentifierConsumer(
|
||||
joinType,
|
||||
parserJoin.FETCH() != null,
|
||||
alias,
|
||||
sqmRoot,
|
||||
processingStateStack.getCurrent()
|
||||
);
|
||||
|
||||
identifierConsumerStack.push( identifierConsumer );
|
||||
semanticPathPartStack.push(
|
||||
new SemanticPathPartQualifiedJoinPath(
|
||||
sqmRoot,
|
||||
joinType,
|
||||
parserJoin.FETCH() != null,
|
||||
alias
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
final SqmQualifiedJoin join = (SqmQualifiedJoin) parserJoin.qualifiedJoinRhs().path().accept( this );
|
||||
|
@ -1052,23 +1001,17 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
processingStateStack.getCurrent().getPathRegistry().register( join );
|
||||
|
||||
if ( parserJoin.qualifiedJoinPredicate() != null ) {
|
||||
identifierConsumerStack.push(
|
||||
new QualifiedJoinPredicateDotIdentifierConsumer(
|
||||
processingStateStack::getCurrent,
|
||||
join,
|
||||
parserJoin.qualifiedJoinPredicate().getText()
|
||||
)
|
||||
);
|
||||
semanticPathPartStack.push( new SemanticPathPartJoinPredicate( join ) );
|
||||
try {
|
||||
join.setJoinPredicate( (SqmPredicate) parserJoin.qualifiedJoinPredicate().predicate().accept( this ) );
|
||||
}
|
||||
finally {
|
||||
identifierConsumerStack.pop();
|
||||
semanticPathPartStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
identifierConsumerStack.pop();
|
||||
semanticPathPartStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2258,7 +2201,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
);
|
||||
}
|
||||
default: {
|
||||
throw new SqmProductionException( "unrecognized cast target type: " + text);
|
||||
throw new HqlInterpretationException( "unrecognized cast target type: " + text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2649,18 +2592,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
if ( ctx.syntacticDomainPath() != null ) {
|
||||
final SemanticPathPart syntacticNavigablePathResult = visitSyntacticDomainPath( ctx.syntacticDomainPath() );
|
||||
if ( ctx.pathContinuation() != null ) {
|
||||
identifierConsumerStack.push(
|
||||
new BasicDotIdentifierConsumer( syntacticNavigablePathResult, processingStateStack::getCurrent ) {
|
||||
@Override
|
||||
protected void reset() {
|
||||
}
|
||||
}
|
||||
);
|
||||
semanticPathPartStack.push( syntacticNavigablePathResult );
|
||||
try {
|
||||
return (SemanticPathPart) ctx.pathContinuation().accept( this );
|
||||
}
|
||||
finally {
|
||||
identifierConsumerStack.pop();
|
||||
semanticPathPartStack.pop();
|
||||
}
|
||||
}
|
||||
return syntacticNavigablePathResult;
|
||||
|
@ -2706,26 +2643,26 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
final int numberOfContinuations = ctx.dotIdentifierSequenceContinuation().size();
|
||||
final boolean hasContinuations = numberOfContinuations != 0;
|
||||
|
||||
final DotIdentifierConsumer dotIdentifierConsumer = identifierConsumerStack.getCurrent();
|
||||
final SemanticPathPart currentPathPart = semanticPathPartStack.getCurrent();
|
||||
|
||||
dotIdentifierConsumer.consumeIdentifier(
|
||||
SemanticPathPart result = currentPathPart.resolvePathPart(
|
||||
ctx.identifier().getText(),
|
||||
true,
|
||||
! hasContinuations
|
||||
!hasContinuations,
|
||||
this
|
||||
);
|
||||
|
||||
if ( hasContinuations ) {
|
||||
int i = 1;
|
||||
for ( HqlParser.DotIdentifierSequenceContinuationContext continuation : ctx.dotIdentifierSequenceContinuation() ) {
|
||||
dotIdentifierConsumer.consumeIdentifier(
|
||||
result = result.resolvePathPart(
|
||||
continuation.identifier().getText(),
|
||||
false,
|
||||
i++ >= numberOfContinuations
|
||||
i++ >= numberOfContinuations,
|
||||
this
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return dotIdentifierConsumer.getConsumedPart();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2743,15 +2680,12 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
SqmPath<?> result = resolveTreatedPath( sqmPath, treatTarget );
|
||||
|
||||
if ( ctx.pathContinuation() != null ) {
|
||||
identifierConsumerStack.push(
|
||||
new BasicDotIdentifierConsumer( sqmPath, processingStateStack::getCurrent )
|
||||
);
|
||||
|
||||
semanticPathPartStack.push( result );
|
||||
try {
|
||||
result = consumeDomainPath( ctx.pathContinuation().dotIdentifierSequence() );
|
||||
}
|
||||
finally {
|
||||
identifierConsumerStack.pop();
|
||||
semanticPathPartStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2820,9 +2754,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
|
||||
|
||||
private SqmPath consumeDomainPath(HqlParser.PathContext parserPath) {
|
||||
parserPath.accept( this );
|
||||
final DotIdentifierConsumer dotIdentifierConsumer = identifierConsumerStack.getCurrent();
|
||||
final SemanticPathPart consumedPart = dotIdentifierConsumer.getConsumedPart();
|
||||
final SemanticPathPart consumedPart = (SemanticPathPart) parserPath.accept( this );
|
||||
if ( consumedPart instanceof SqmPath ) {
|
||||
return (SqmPath) consumedPart;
|
||||
}
|
||||
|
@ -2832,9 +2764,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
|
||||
|
||||
private SqmPath consumeDomainPath(HqlParser.DotIdentifierSequenceContext sequence) {
|
||||
sequence.accept( this );
|
||||
final DotIdentifierConsumer dotIdentifierConsumer = identifierConsumerStack.getCurrent();
|
||||
final SemanticPathPart consumedPart = dotIdentifierConsumer.getConsumedPart();
|
||||
final SemanticPathPart consumedPart = (SemanticPathPart) sequence.accept( this );
|
||||
if ( consumedPart instanceof SqmPath ) {
|
||||
return (SqmPath) consumedPart;
|
||||
}
|
||||
|
@ -2886,7 +2816,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
public void addDowncast(
|
||||
SqmFrom sqmFrom,
|
||||
IdentifiableDomainType downcastTarget) {
|
||||
( (MutableUsageDetails) sqmFrom.getUsageDetails() ).addDownCast( false, downcastTarget, downcastLocation );
|
||||
// ( (MutableUsageDetails) sqmFrom.getUsageDetails() ).addDownCast( false, downcastTarget, downcastLocation );
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2895,7 +2826,8 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
public void addDowncast(
|
||||
SqmFrom sqmFrom,
|
||||
IdentifiableDomainType downcastTarget) {
|
||||
( (MutableUsageDetails) sqmFrom.getUsageDetails() ).addDownCast( true, downcastTarget, DowncastLocation.FROM );
|
||||
// ( (MutableUsageDetails) sqmFrom.getUsageDetails() ).addDownCast( true, downcastTarget, DowncastLocation.FROM );
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.QueryLogger;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.AliasCollisionException;
|
||||
import org.hibernate.query.sqm.ParsingException;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.SqmTreeCreationLogger;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||
|
||||
/**
|
||||
* Container for indexing needed while building an SQM tree.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmPathRegistryImpl implements SqmPathRegistry {
|
||||
private final SqmCreationProcessingState associatedProcessingState;
|
||||
|
||||
private final Map<NavigablePath, SqmPath> sqmPathByPath = new HashMap<>();
|
||||
private final Map<NavigablePath, SqmFrom> sqmFromByPath = new HashMap<>();
|
||||
|
||||
private final Map<String, SqmFrom> sqmFromByAlias = new HashMap<>();
|
||||
|
||||
private final LinkedHashMap<String, SqmSelection> sqmSelectionsByAlias = new LinkedHashMap<>();
|
||||
|
||||
public SqmPathRegistryImpl(SqmCreationProcessingState associatedProcessingState) {
|
||||
this.associatedProcessingState = associatedProcessingState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(SqmPath sqmPath) {
|
||||
SqmTreeCreationLogger.LOGGER.tracef( "SqmProcessingIndex#register(SqmPath) : %s", sqmPath.getNavigablePath().getFullPath() );
|
||||
|
||||
// Generally we:
|
||||
// 1) add the path to the path-by-path map
|
||||
// 2) if the path is a from, we add it to the from-by-path map
|
||||
// 3) if the path is a from and defines an alias, we add it to the from-by-alias map
|
||||
//
|
||||
// Regarding part #1 (add to the path-by-path map), it is ok for a SqmFrom to replace a
|
||||
// non-SqmFrom. This should equate to, e.g., an implicit join.
|
||||
|
||||
if ( sqmPath instanceof SqmFrom ) {
|
||||
final SqmFrom sqmFrom = (SqmFrom) sqmPath;
|
||||
|
||||
final String alias = sqmPath.getExplicitAlias();
|
||||
if ( alias != null ) {
|
||||
final SqmFrom previousFrom = sqmFromByAlias.put( alias, sqmFrom );
|
||||
if ( previousFrom != null ) {
|
||||
throw new AliasCollisionException(
|
||||
String.format(
|
||||
Locale.ENGLISH,
|
||||
"Alias [%s] used for multiple from-clause elements : %s, %s",
|
||||
alias,
|
||||
previousFrom,
|
||||
sqmPath
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final SqmFrom previousFromByPath = sqmFromByPath.put( sqmPath.getNavigablePath(), sqmFrom );
|
||||
|
||||
if ( previousFromByPath != null ) {
|
||||
// this should never happen
|
||||
throw new ParsingException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Registration for SqmFrom [%s] overrode previous registration: %s -> %s",
|
||||
sqmPath.getNavigablePath(),
|
||||
previousFromByPath,
|
||||
sqmFrom
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final SqmPath previousPath = sqmPathByPath.put( sqmPath.getNavigablePath(), sqmPath );
|
||||
|
||||
if ( previousPath instanceof SqmFrom ) {
|
||||
// this should never happen
|
||||
throw new ParsingException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Registration for path [%s] overrode previous registration: %s -> %s",
|
||||
sqmPath.getNavigablePath(),
|
||||
previousPath,
|
||||
sqmPath
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath findPath(NavigablePath path) {
|
||||
final SqmPath found = sqmPathByPath.get( path );
|
||||
if ( found != null ) {
|
||||
return found;
|
||||
}
|
||||
|
||||
if ( associatedProcessingState.getParentProcessingState() != null ) {
|
||||
final SqmFrom containingQueryFrom = associatedProcessingState.getParentProcessingState()
|
||||
.getPathRegistry()
|
||||
.findFromByPath( path );
|
||||
if ( containingQueryFrom != null ) {
|
||||
// todo (6.0) create a correlation?
|
||||
return containingQueryFrom;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFrom findFromByPath(NavigablePath navigablePath) {
|
||||
final SqmFrom found = sqmFromByPath.get( navigablePath );
|
||||
if ( found != null ) {
|
||||
return found;
|
||||
}
|
||||
|
||||
if ( associatedProcessingState.getParentProcessingState() != null ) {
|
||||
final SqmFrom containingQueryFrom = associatedProcessingState.getParentProcessingState()
|
||||
.getPathRegistry()
|
||||
.findFromByPath( navigablePath );
|
||||
if ( containingQueryFrom != null ) {
|
||||
// todo (6.0) create a correlation?
|
||||
return containingQueryFrom;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFrom findFromByAlias(String alias) {
|
||||
final SqmFrom registered = sqmFromByAlias.get( alias );
|
||||
if ( registered != null ) {
|
||||
return registered;
|
||||
}
|
||||
|
||||
if ( associatedProcessingState.getParentProcessingState() != null ) {
|
||||
return associatedProcessingState.getParentProcessingState().getPathRegistry().findFromByAlias( alias );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmFrom findFromExposing(String navigableName) {
|
||||
// todo (6.0) : atm this checks every from-element every time, the idea being to make sure there
|
||||
// is only one such element obviously that scales poorly across larger from-clauses. Another
|
||||
// (configurable?) option would be to simply pick the first one as a perf optimization
|
||||
|
||||
SqmFrom found = null;
|
||||
for ( SqmFrom fromElement : sqmFromByPath.values() ) {
|
||||
if ( definesAttribute( fromElement.getReferencedPathSource(), navigableName ) ) {
|
||||
if ( found != null ) {
|
||||
throw new IllegalStateException( "Multiple from-elements expose unqualified attribute : " + navigableName );
|
||||
}
|
||||
found = fromElement;
|
||||
}
|
||||
}
|
||||
|
||||
if ( found == null ) {
|
||||
if ( associatedProcessingState.getParentProcessingState() != null ) {
|
||||
QueryLogger.QUERY_LOGGER.debugf(
|
||||
"Unable to resolve unqualified attribute [%s] in local from-clause; checking parent ",
|
||||
navigableName
|
||||
);
|
||||
found = associatedProcessingState.getParentProcessingState().getPathRegistry().findFromExposing( navigableName );
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath resolvePath(NavigablePath navigablePath, Function<NavigablePath, SqmPath> creator) {
|
||||
SqmTreeCreationLogger.LOGGER.tracef( "SqmProcessingIndex#resolvePath(NavigablePath) : %s", navigablePath );
|
||||
|
||||
final SqmPath existing = sqmPathByPath.get( navigablePath );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final SqmPath sqmPath = creator.apply( navigablePath );
|
||||
register( sqmPath );
|
||||
return sqmPath;
|
||||
}
|
||||
|
||||
private boolean definesAttribute(SqmPathSource containerType, String name) {
|
||||
return containerType.findSubPathSource( name ) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmSelection findSelectionByAlias(String alias) {
|
||||
return sqmSelectionsByAlias.get( alias );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmSelection findSelectionByPosition(int position) {
|
||||
// NOTE : 1-based
|
||||
// so incoming position must be between >= 1 and <= map.size
|
||||
|
||||
if ( position >= 1 && position <= sqmSelectionsByAlias.size() ) {
|
||||
int i = 1;
|
||||
for ( Map.Entry<String, SqmSelection> entry : sqmSelectionsByAlias.entrySet() ) {
|
||||
if ( position == i++ ) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(SqmSelection selection) {
|
||||
if ( selection.getAlias() != null ) {
|
||||
checkResultVariable( selection );
|
||||
sqmSelectionsByAlias.put( selection.getAlias(), selection );
|
||||
}
|
||||
}
|
||||
|
||||
private void checkResultVariable(SqmSelection selection) {
|
||||
final String alias = selection.getAlias();
|
||||
|
||||
if ( sqmSelectionsByAlias.containsKey( alias ) ) {
|
||||
throw new AliasCollisionException(
|
||||
String.format(
|
||||
Locale.ENGLISH,
|
||||
"Alias [%s] is already used in same select clause",
|
||||
alias
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
final SqmFrom registeredFromElement = sqmFromByAlias.get( alias );
|
||||
if ( registeredFromElement != null ) {
|
||||
if ( !registeredFromElement.equals( selection.getSelectableNode() ) ) {
|
||||
throw new AliasCollisionException(
|
||||
String.format(
|
||||
Locale.ENGLISH,
|
||||
"Alias [%s] used in select-clause [%s] also used in from-clause [%s]",
|
||||
alias,
|
||||
selection.getSelectableNode(),
|
||||
registeredFromElement
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,14 @@
|
|||
*/
|
||||
package org.hibernate.query.hql.spi;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
|
||||
import org.hibernate.query.spi.NamedQueryMemento;
|
||||
|
||||
/**
|
||||
|
@ -25,4 +32,129 @@ public interface NamedHqlQueryMemento extends NamedQueryMemento {
|
|||
|
||||
@Override
|
||||
<T> HqlQueryImplementor<T> toQuery(SharedSessionContractImplementor session, Class<T> resultType);
|
||||
|
||||
/**
|
||||
* Delegate used in creating named HQL query mementos for queries defined in
|
||||
* annotations, hbm.xml or orm.xml
|
||||
*/
|
||||
class Builder {
|
||||
protected String name;
|
||||
protected String query;
|
||||
protected boolean cacheable;
|
||||
protected String cacheRegion;
|
||||
protected Integer timeout;
|
||||
protected Integer fetchSize;
|
||||
protected FlushMode flushMode;
|
||||
protected CacheMode cacheMode;
|
||||
protected boolean readOnly;
|
||||
protected String comment;
|
||||
protected Map parameterTypes;
|
||||
protected LockOptions lockOptions;
|
||||
protected Integer firstResult;
|
||||
protected Integer maxResults;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public Builder(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Builder setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setQuery(String query) {
|
||||
this.query = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCacheable(boolean cacheable) {
|
||||
this.cacheable = cacheable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCacheRegion(String cacheRegion) {
|
||||
this.cacheRegion = cacheRegion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTimeout(Integer timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFetchSize(Integer fetchSize) {
|
||||
this.fetchSize = fetchSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFlushMode(FlushMode flushMode) {
|
||||
this.flushMode = flushMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCacheMode(CacheMode cacheMode) {
|
||||
this.cacheMode = cacheMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setComment(String comment) {
|
||||
this.comment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addParameterType(String name, String typeName) {
|
||||
if ( this.parameterTypes == null ) {
|
||||
this.parameterTypes = new HashMap();
|
||||
}
|
||||
this.parameterTypes.put( name, typeName );
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setParameterTypes(Map parameterTypes) {
|
||||
this.parameterTypes = parameterTypes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLockOptions(LockOptions lockOptions) {
|
||||
this.lockOptions = lockOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFirstResult(Integer firstResult) {
|
||||
this.firstResult = firstResult;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMaxResults(Integer maxResults) {
|
||||
this.maxResults = maxResults;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NamedHqlQueryMemento createNamedQueryDefinition() {
|
||||
return new NamedHqlQueryMementoImpl(
|
||||
name,
|
||||
query,
|
||||
cacheable,
|
||||
cacheRegion,
|
||||
timeout,
|
||||
lockOptions,
|
||||
fetchSize,
|
||||
flushMode,
|
||||
cacheMode,
|
||||
readOnly,
|
||||
comment,
|
||||
parameterTypes,
|
||||
firstResult,
|
||||
maxResults
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.sqm.produce.path.spi;
|
||||
package org.hibernate.query.hql.spi;
|
||||
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
|
@ -27,13 +27,11 @@ import org.hibernate.query.sqm.tree.domain.SqmNavigableReference;
|
|||
public interface SemanticPathPart {
|
||||
SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState);
|
||||
|
||||
SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState);
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.sqm.produce;
|
||||
package org.hibernate.query.hql.spi;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -12,6 +12,7 @@ import org.hibernate.Incubating;
|
|||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.from.SqmFrom;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSelection;
|
||||
|
||||
/**
|
||||
* Registry for SqmPath references providing the ability to access them
|
||||
|
@ -24,6 +25,12 @@ import org.hibernate.query.sqm.tree.from.SqmFrom;
|
|||
public interface SqmPathRegistry {
|
||||
void register(SqmPath sqmPath);
|
||||
|
||||
SqmSelection findSelectionByAlias(String alias);
|
||||
|
||||
SqmSelection findSelectionByPosition(int position);
|
||||
|
||||
void register(SqmSelection selection);
|
||||
|
||||
/**
|
||||
* Find a SqmFrom by its identification variable (alias). Will search any
|
||||
* parent contexts as well
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -14,12 +13,13 @@ import java.util.function.Consumer;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
|
||||
import org.hibernate.procedure.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.query.hql.SemanticQueryProducer;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
import org.hibernate.query.spi.NamedQueryRepository;
|
||||
import org.hibernate.query.spi.NamedResultSetMappingMemento;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.spi.QueryPlanCache;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
|
||||
|
@ -131,6 +131,8 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
|
|||
Map<String,HibernateException> errors = new HashMap<>();
|
||||
|
||||
final SemanticQueryProducer sqmProducer = queryEngine.getSemanticQueryProducer();
|
||||
final QueryPlanCache queryPlanCache = queryEngine.getQueryPlanCache();
|
||||
final boolean cachingEnabled = queryPlanCache.isEnabled();
|
||||
|
||||
// Check named HQL queries
|
||||
log.debugf( "Checking %s named HQL queries", hqlMementoMap.size() );
|
||||
|
@ -139,8 +141,11 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
|
|||
try {
|
||||
log.debugf( "Checking named query: %s", hqlMemento.getName() );
|
||||
final SqmStatement sqmStatement = sqmProducer.interpret( hqlMemento.getQueryString() );
|
||||
// todo (6.0) : need to cache these; however atm that requires producing a SqmQueryImpl
|
||||
// queryEngine.getQueryPlanCache().getHQLQueryPlan( hqlMemento.getQueryString(), false, Collections.EMPTY_MAP );
|
||||
|
||||
if ( cachingEnabled ) {
|
||||
// todo (6.0) : need to cache these; however atm that requires producing a SqmQueryImpl
|
||||
// queryEngine.getQueryPlanCache().getHQLQueryPlan( hqlMemento.getQueryString(), false, Collections.EMPTY_MAP );
|
||||
}
|
||||
}
|
||||
catch ( HibernateException e ) {
|
||||
errors.put( hqlMemento.getName(), e );
|
||||
|
|
|
@ -54,6 +54,11 @@ public class QueryPlanCacheDisabledImpl implements QueryPlanCache {
|
|||
public void cacheSqmStatement(String key, SqmStatement sqmStatement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
|
|
@ -99,6 +99,11 @@ public class QueryPlanCacheStandardImpl implements QueryPlanCache {
|
|||
sqmStatementCache.putIfAbsent( queryString, sqmStatement );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// todo (6.0) : clear maps/caches and LOG
|
||||
|
|
|
@ -34,7 +34,14 @@ public interface ProcedureParameter<T> extends QueryParameter<T> {
|
|||
* that it is ignored.
|
||||
*
|
||||
* @see ParameterRegistrationImplementor#isPassNullsEnabled()
|
||||
*
|
||||
* @deprecated (since 6.0) : Passing null or not is now triggered by whether
|
||||
* setting the parameter was called at all. In other words a distinction is
|
||||
* made between calling `setParameter` passing {@code null} versus not calling
|
||||
* `setParameter` at all. In the first case, we pass along the {@code null}; in
|
||||
* the second we do not pass {@code null}.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isPassNullsEnabled();
|
||||
|
||||
/**
|
||||
|
@ -44,6 +51,9 @@ public interface ProcedureParameter<T> extends QueryParameter<T> {
|
|||
* @param enabled {@code true} indicates that the NULL should be passed; {@code false} indicates it should not.
|
||||
*
|
||||
* @see org.hibernate.procedure.ParameterRegistration#enablePassingNulls
|
||||
*
|
||||
* @deprecated (since 6.0) : see {@link #isPassNullsEnabled}
|
||||
*/
|
||||
@Deprecated
|
||||
void enablePassingNulls(boolean enabled);
|
||||
}
|
||||
|
|
|
@ -6,8 +6,14 @@
|
|||
*/
|
||||
package org.hibernate.query.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.ParameterMode;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
|
@ -22,7 +28,7 @@ import org.hibernate.procedure.internal.Util;
|
|||
public abstract class AbstractNamedQueryMemento implements NamedQueryMemento {
|
||||
private final String name;
|
||||
|
||||
private final List<ParameterMemento> parameterMementos;
|
||||
private final List<? extends ParameterMemento> parameterMementos;
|
||||
|
||||
private final Boolean cacheable;
|
||||
private final String cacheRegion;
|
||||
|
@ -42,7 +48,7 @@ public abstract class AbstractNamedQueryMemento implements NamedQueryMemento {
|
|||
|
||||
public AbstractNamedQueryMemento(
|
||||
String name,
|
||||
List<ParameterMemento> parameterMementos,
|
||||
List<? extends ParameterMemento> parameterMementos,
|
||||
Boolean cacheable,
|
||||
String cacheRegion,
|
||||
CacheMode cacheMode,
|
||||
|
@ -169,4 +175,192 @@ public abstract class AbstractNamedQueryMemento implements NamedQueryMemento {
|
|||
query.setComment( comment );
|
||||
}
|
||||
}
|
||||
|
||||
protected static abstract class AbstractBuilder<T extends AbstractBuilder> {
|
||||
private final String name;
|
||||
|
||||
private List<ParameterDefinition> parameterDescriptors;
|
||||
|
||||
private Set<String> querySpaces;
|
||||
private Boolean cacheable;
|
||||
private String cacheRegion;
|
||||
private CacheMode cacheMode;
|
||||
|
||||
private FlushMode flushMode;
|
||||
private Boolean readOnly;
|
||||
|
||||
private LockOptions lockOptions;
|
||||
|
||||
private Integer timeout;
|
||||
private Integer fetchSize;
|
||||
|
||||
private String comment;
|
||||
|
||||
private Map<String,Object> hints;
|
||||
|
||||
public AbstractBuilder(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected abstract T getThis();
|
||||
|
||||
public T addParameter(Class javaType, ParameterMode mode) {
|
||||
return addParameter(
|
||||
createPositionalParameter(
|
||||
parameterDescriptors.size() + 1,
|
||||
javaType,
|
||||
mode
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract ParameterDefinition createPositionalParameter(int i, Class javaType, ParameterMode mode);
|
||||
|
||||
public T addParameter(ParameterDefinition parameterDefinition) {
|
||||
if ( parameterDescriptors == null ) {
|
||||
parameterDescriptors = new ArrayList<>();
|
||||
}
|
||||
|
||||
parameterDescriptors.add( parameterDefinition );
|
||||
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T addParameter(String name, Class javaType, ParameterMode mode) {
|
||||
if ( parameterDescriptors == null ) {
|
||||
parameterDescriptors = new ArrayList<>();
|
||||
}
|
||||
|
||||
parameterDescriptors.add( createNamedParameter( name, javaType, mode ) );
|
||||
|
||||
return getThis();
|
||||
}
|
||||
|
||||
protected abstract ParameterDefinition createNamedParameter(String name, Class javaType, ParameterMode mode);
|
||||
|
||||
|
||||
public T addQuerySpaces(Set<String> querySpaces) {
|
||||
if ( querySpaces == null || querySpaces.isEmpty() ) {
|
||||
return getThis();
|
||||
}
|
||||
|
||||
if ( this.querySpaces == null ) {
|
||||
this.querySpaces = new HashSet<>();
|
||||
}
|
||||
this.querySpaces.addAll( querySpaces );
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T addQuerySpace(String space) {
|
||||
if ( this.querySpaces == null ) {
|
||||
this.querySpaces = new HashSet<>();
|
||||
}
|
||||
this.querySpaces.add( space );
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setCacheable(Boolean cacheable) {
|
||||
this.cacheable = cacheable;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setCacheRegion(String cacheRegion) {
|
||||
this.cacheRegion = cacheRegion;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setCacheMode(CacheMode cacheMode) {
|
||||
this.cacheMode = cacheMode;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setLockOptions(LockOptions lockOptions) {
|
||||
this.lockOptions = lockOptions;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setTimeout(Integer timeout) {
|
||||
this.timeout = timeout;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setFlushMode(FlushMode flushMode) {
|
||||
this.flushMode = flushMode;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setReadOnly(Boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setFetchSize(Integer fetchSize) {
|
||||
this.fetchSize = fetchSize;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public T setComment(String comment) {
|
||||
this.comment = comment;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
public Set<String> getQuerySpaces() {
|
||||
return querySpaces;
|
||||
}
|
||||
|
||||
public Boolean getCacheable() {
|
||||
return cacheable;
|
||||
}
|
||||
|
||||
public String getCacheRegion() {
|
||||
return cacheRegion;
|
||||
}
|
||||
|
||||
public CacheMode getCacheMode() {
|
||||
return cacheMode;
|
||||
}
|
||||
|
||||
public FlushMode getFlushMode() {
|
||||
return flushMode;
|
||||
}
|
||||
|
||||
public Boolean getReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
public LockOptions getLockOptions() {
|
||||
return lockOptions;
|
||||
}
|
||||
|
||||
public Integer getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public Integer getFetchSize() {
|
||||
return fetchSize;
|
||||
}
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
protected List<ParameterDefinition> getParameterDescriptors() {
|
||||
return parameterDescriptors;
|
||||
}
|
||||
|
||||
public void addHint(String name, Object value) {
|
||||
if ( hints == null ) {
|
||||
hints = new HashMap<>();
|
||||
}
|
||||
hints.put( name, value );
|
||||
}
|
||||
|
||||
public Map<String, Object> getHints() {
|
||||
return hints;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.procedure.NamedCallableQueryMemento;
|
||||
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
|
||||
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
|
||||
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ public interface QueryPlanCache {
|
|||
SqmStatement getSqmStatement(String queryString);
|
||||
void cacheSqmStatement(String key, SqmStatement sqmStatement);
|
||||
|
||||
boolean isEnabled();
|
||||
|
||||
/**
|
||||
* Close the cache when the SessionFactory is closed.
|
||||
* <p>
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.hibernate.internal.util.collections.Stack;
|
|||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.SqmPathRegistry;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.produce.SqmQuerySpecCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.spi.ImplicitAliasGenerator;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationContext;
|
||||
|
|
|
@ -27,7 +27,9 @@ import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmEnumLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmFieldLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||
|
@ -157,6 +159,10 @@ public interface SemanticQueryWalker<T> {
|
|||
|
||||
T visitLiteral(SqmLiteral<?> literal);
|
||||
|
||||
T visitEnumLiteral(SqmEnumLiteral sqmEnumLiteral);
|
||||
|
||||
T visitFieldLiteral(SqmFieldLiteral sqmFieldLiteral);
|
||||
|
||||
T visitTuple(SqmTuple<?> sqmTuple);
|
||||
|
||||
T visitBinaryArithmeticExpression(SqmBinaryArithmetic<?> expression);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.query.sqm.produce;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.SqmQuery;
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.produce.internal;
|
||||
|
||||
import org.hibernate.query.hql.internal.SqmProcessingIndex;
|
||||
import org.hibernate.query.hql.internal.SqmPathRegistryImpl;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.SqmPathRegistry;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.SqmQuery;
|
||||
|
||||
|
@ -19,7 +19,7 @@ public class SqmCreationProcessingStateImpl implements SqmCreationProcessingStat
|
|||
private final SqmCreationState creationState;
|
||||
private final SqmQuery<?> processingQuery;
|
||||
|
||||
private final SqmProcessingIndex processingIndex = new SqmProcessingIndex( this );
|
||||
private final SqmPathRegistryImpl processingIndex = new SqmPathRegistryImpl( this );
|
||||
|
||||
public SqmCreationProcessingStateImpl(
|
||||
SqmQuery<?> processingQuery,
|
||||
|
@ -38,7 +38,7 @@ public class SqmCreationProcessingStateImpl implements SqmCreationProcessingStat
|
|||
return processingQuery;
|
||||
}
|
||||
|
||||
protected SqmProcessingIndex getProcessingIndex() {
|
||||
protected SqmPathRegistryImpl getProcessingIndex() {
|
||||
return processingIndex;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ public class SqmQuerySpecCreationProcessingStateStandardImpl
|
|||
|
||||
@Override
|
||||
public void registerSelection(SqmSelection selection) {
|
||||
getProcessingIndex().registerSelection( selection );
|
||||
getProcessingIndex().register( selection );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.hibernate.metamodel.model.mapping.spi.BasicValuedNavigable;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
|
||||
|
@ -49,7 +49,6 @@ public class SqmStaticEnumReference<T extends Enum<T>>
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new UnsupportedOperationException( );
|
||||
|
@ -58,7 +57,6 @@ public class SqmStaticEnumReference<T extends Enum<T>>
|
|||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new UnsupportedOperationException( );
|
||||
|
|
|
@ -14,8 +14,8 @@ import org.hibernate.metamodel.model.mapping.spi.BasicValuedNavigable;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.SqmProductionException;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.HqlInterpretationException;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
|
||||
|
@ -43,7 +43,7 @@ public class SqmStaticFieldReference<T>
|
|||
this.fieldValue = referencedField.get( null );
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new SqmProductionException(
|
||||
throw new HqlInterpretationException(
|
||||
"Could not access field value : `"
|
||||
+ referencedField.getDeclaringClass().getTypeName() + "."
|
||||
+ referencedField.getName() + "`",
|
||||
|
@ -62,7 +62,6 @@ public class SqmStaticFieldReference<T>
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new UnsupportedOperationException( );
|
||||
|
@ -71,7 +70,6 @@ public class SqmStaticFieldReference<T>
|
|||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new UnsupportedOperationException( );
|
||||
|
@ -111,7 +109,7 @@ public class SqmStaticFieldReference<T>
|
|||
);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new SqmProductionException(
|
||||
throw new HqlInterpretationException(
|
||||
"Could not access field value : `"
|
||||
+ referencedField.getDeclaringClass().getTypeName() + "."
|
||||
+ referencedField.getName() + "`",
|
||||
|
@ -131,7 +129,7 @@ public class SqmStaticFieldReference<T>
|
|||
);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new SqmProductionException(
|
||||
throw new HqlInterpretationException(
|
||||
"Could not access field value : `"
|
||||
+ referencedField.getDeclaringClass().getTypeName() + "."
|
||||
+ referencedField.getName() + "`",
|
||||
|
@ -151,7 +149,7 @@ public class SqmStaticFieldReference<T>
|
|||
);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new SqmProductionException(
|
||||
throw new HqlInterpretationException(
|
||||
"Could not access field value : `"
|
||||
+ referencedField.getDeclaringClass().getTypeName() + "."
|
||||
+ referencedField.getName() + "`",
|
||||
|
@ -171,7 +169,7 @@ public class SqmStaticFieldReference<T>
|
|||
);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new SqmProductionException(
|
||||
throw new HqlInterpretationException(
|
||||
"Could not access field value : `"
|
||||
+ referencedField.getDeclaringClass().getTypeName() + "."
|
||||
+ referencedField.getName() + "`",
|
||||
|
|
|
@ -7,10 +7,8 @@
|
|||
package org.hibernate.query.sqm.produce.spi;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.annotations.Remove;
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationProcessingState;
|
||||
import org.hibernate.query.sqm.produce.SqmQuerySpecCreationProcessingState;
|
||||
|
||||
/**
|
||||
* Models the state pertaining to the creation of a single SQM.
|
||||
|
@ -38,31 +36,7 @@ public interface SqmCreationState {
|
|||
*/
|
||||
Stack<SqmCreationProcessingState> getProcessingStateStack();
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Would prefer to use NavigablePath to serve the role that uid currently
|
||||
// serves
|
||||
|
||||
String generateUniqueIdentifier();
|
||||
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Below are the methods we want to re-think in terms of how SQM creation
|
||||
// happens - SqmPath, etc
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated we want to re-think in terms of how SQM creation happens
|
||||
*/
|
||||
@Remove
|
||||
@Deprecated
|
||||
ImplicitAliasGenerator getImplicitAliasGenerator();
|
||||
|
||||
/**
|
||||
* @deprecated we want to re-think in terms of how SQM creation happens
|
||||
*/
|
||||
@Remove
|
||||
@Deprecated
|
||||
SqmQuerySpecCreationProcessingState getCurrentQuerySpecProcessingState();
|
||||
default SqmCreationProcessingState getCurrentProcessingState() {
|
||||
return getProcessingStateStack().getCurrent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.UnknownPathException;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
|
@ -105,7 +105,6 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
final NavigablePath subNavPath = getNavigablePath().append( name );
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
|||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.hibernate.query.PathException;
|
|||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
|
||||
/**
|
||||
|
@ -51,7 +51,6 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
return null;
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
|
||||
|
@ -40,7 +40,6 @@ public class SqmBasicValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException( "Basic-valued path [" + getNavigablePath() + "] cannot be de-referenced : " + name );
|
||||
|
|
|
@ -14,8 +14,8 @@ import org.hibernate.query.sqm.SqmJoinable;
|
|||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.UnknownPathException;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.SqmPathRegistry;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.SqmJoinType;
|
||||
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
|
||||
|
@ -50,7 +50,6 @@ public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
final SqmPathSource<?> subPathSource = getReferencedPathSource().findSubPathSource( name );
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.hibernate.query.sqm.NodeBuilder;
|
|||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationHelper;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,6 @@ public class SqmEntityValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
final SqmPathSource referencedPathSource = getReferencedPathSource();
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.hibernate.query.NavigablePath;
|
|||
import org.hibernate.query.PathException;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
|
@ -57,7 +57,6 @@ public class SqmIndexedCollectionAccessPath<T> extends AbstractSqmPath<T> implem
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
final SqmPathSource subPathSource = getReferencedPathSource().getElementPathSource().findSubPathSource( name );
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
|||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,6 @@ public class SqmMaxElementPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
|||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,6 @@ public class SqmMaxIndexPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
return indexPathSource.createSqmPath( this, creationState );
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
|||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,6 @@ public class SqmMinElementPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
|||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,6 @@ public class SqmMinIndexPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
|||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
return indexPathSource.createSqmPath( this, creationState );
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.hibernate.query.SemanticException;
|
|||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.query.sqm.produce.SqmCreationHelper;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
|
@ -88,7 +88,6 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
|
|||
@Override
|
||||
default SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException( "Non-plural path [" + currentContextKey + "] cannot be index-accessed" );
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.hibernate.query.NavigablePath;
|
|||
import org.hibernate.query.PathException;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.path.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
|
||||
/**
|
||||
|
@ -65,7 +65,6 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
|
|||
@SuppressWarnings("unchecked")
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
// this is a reference to a collection outside of the from-clause...
|
||||
|
|
|
@ -55,10 +55,9 @@ public class SqmTreatedListJoin<O,T, S extends T> extends SqmListJoin<O,S> imple
|
|||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
String currentContextKey,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
return getWrappedPath().resolveIndexedAccess( selector, currentContextKey, isTerminal, creationState );
|
||||
return getWrappedPath().resolveIndexedAccess( selector, isTerminal, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.persistence.criteria.Expression;
|
||||
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.spi.EnumJavaDescriptor;
|
||||
|
||||
/**
|
||||
* Specialized SQM literal defined by an enum reference. E.g.
|
||||
* {@code ".. where p.sex = Sex.MALE"}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmEnumLiteral implements SqmExpression<Enum>, SqmExpressable<Enum>, SemanticPathPart {
|
||||
private final Enum enumValue;
|
||||
private final EnumJavaDescriptor<Enum> referencedEnumTypeDescriptor;
|
||||
private final String enumValueName;
|
||||
private final NodeBuilder nodeBuilder;
|
||||
|
||||
private SqmExpressable<Enum> expressable;
|
||||
|
||||
public SqmEnumLiteral(
|
||||
Enum enumValue,
|
||||
EnumJavaDescriptor<Enum> referencedEnumTypeDescriptor,
|
||||
String enumValueName,
|
||||
NodeBuilder nodeBuilder) {
|
||||
this.enumValue = enumValue;
|
||||
this.referencedEnumTypeDescriptor = referencedEnumTypeDescriptor;
|
||||
this.enumValueName = enumValueName;
|
||||
this.nodeBuilder = nodeBuilder;
|
||||
|
||||
this.expressable = this;
|
||||
}
|
||||
|
||||
public Enum getEnumValue() {
|
||||
return enumValue;
|
||||
}
|
||||
|
||||
public String getEnumValueName() {
|
||||
return enumValueName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumJavaDescriptor<Enum> getExpressableJavaTypeDescriptor() {
|
||||
return referencedEnumTypeDescriptor;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// SemanticPathPart
|
||||
|
||||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Static enum reference [%s#%s] cannot be de-referenced",
|
||||
referencedEnumTypeDescriptor.getJavaType().getName(),
|
||||
enumValueName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Static enum reference [%s#%s] cannot be de-referenced",
|
||||
referencedEnumTypeDescriptor.getJavaType().getName(),
|
||||
enumValueName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable<Enum> getNodeType() {
|
||||
return expressable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyInferableType(SqmExpressable<?> type) {
|
||||
//noinspection unchecked
|
||||
this.expressable = (SqmExpressable) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Long> asLong() {
|
||||
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toOrdinal( enumValue ).longValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Integer> asInteger() {
|
||||
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toOrdinal( enumValue ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Float> asFloat() {
|
||||
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toOrdinal( enumValue ).floatValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Double> asDouble() {
|
||||
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toOrdinal( enumValue ).doubleValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<BigDecimal> asBigDecimal() {
|
||||
throw new UnsupportedOperationException( "Enum literal cannot be cast to BigDecimal" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<BigInteger> asBigInteger() {
|
||||
throw new UnsupportedOperationException( "Enum literal cannot be cast to BigInteger" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<String> asString() {
|
||||
return nodeBuilder().literal( getExpressableJavaTypeDescriptor().toName( enumValue ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> SqmExpression<X> as(Class<X> type) {
|
||||
return nodeBuilder().cast( this, type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate isNull() {
|
||||
return nodeBuilder().isNull( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate isNotNull() {
|
||||
return nodeBuilder().isNotNull( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Object... values) {
|
||||
return nodeBuilder().in( this, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Expression<?>... values) {
|
||||
return nodeBuilder().in( this, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Collection<?> values) {
|
||||
return nodeBuilder().in( this, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Expression<Collection<?>> values) {
|
||||
return nodeBuilder().in( this, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitEnumLiteral( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<Enum> getJavaTypeDescriptor() {
|
||||
return getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeBuilder nodeBuilder() {
|
||||
return nodeBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends JpaSelection<?>> getSelectionItems() {
|
||||
// per-JPA
|
||||
throw new IllegalStateException( "Not a compound selection" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompoundSelection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaSelection<Enum> alias(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlias() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.persistence.criteria.Expression;
|
||||
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmFieldLiteral<T> implements SqmExpression<T>, SqmExpressable<T>, SemanticPathPart {
|
||||
private final T value;
|
||||
private final JavaTypeDescriptor<T> fieldOwnerJavaTypeDescriptor;
|
||||
private final String fieldName;
|
||||
private final NodeBuilder nodeBuilder;
|
||||
|
||||
private SqmExpressable<T> expressable;
|
||||
|
||||
public SqmFieldLiteral(
|
||||
T value,
|
||||
JavaTypeDescriptor<T> fieldOwnerJavaTypeDescriptor,
|
||||
String fieldName,
|
||||
NodeBuilder nodeBuilder) {
|
||||
this.value = value;
|
||||
this.fieldOwnerJavaTypeDescriptor = fieldOwnerJavaTypeDescriptor;
|
||||
this.fieldName = fieldName;
|
||||
this.nodeBuilder = nodeBuilder;
|
||||
|
||||
this.expressable = this;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public JavaTypeDescriptor<T> getFieldOwnerJavaTypeDescriptor() {
|
||||
return fieldOwnerJavaTypeDescriptor;
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
public NodeBuilder getNodeBuilder() {
|
||||
return nodeBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpressable<T> getNodeType() {
|
||||
return expressable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyInferableType(SqmExpressable<?> type) {
|
||||
//noinspection unchecked
|
||||
this.expressable = (SqmExpressable) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<T> getExpressableJavaTypeDescriptor() {
|
||||
return expressable.getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<T> getJavaTypeDescriptor() {
|
||||
return getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitFieldLiteral( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeBuilder nodeBuilder() {
|
||||
return nodeBuilder;
|
||||
}
|
||||
@Override
|
||||
public SqmPredicate isNull() {
|
||||
return nodeBuilder().isNull( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate isNotNull() {
|
||||
return nodeBuilder().isNotNull( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Object... values) {
|
||||
return nodeBuilder().in( this, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Expression<?>... values) {
|
||||
return nodeBuilder().in( this, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Collection<?> values) {
|
||||
return nodeBuilder().in( this, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate in(Expression<Collection<?>> values) {
|
||||
return nodeBuilder().in( this, values );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Long> asLong() {
|
||||
//noinspection unchecked
|
||||
return (SqmExpression<Long>) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Integer> asInteger() {
|
||||
//noinspection unchecked
|
||||
return (SqmExpression<Integer>) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Float> asFloat() {
|
||||
//noinspection unchecked
|
||||
return (SqmExpression<Float>) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<Double> asDouble() {
|
||||
//noinspection unchecked
|
||||
return (SqmExpression<Double>) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<BigDecimal> asBigDecimal() {
|
||||
//noinspection unchecked
|
||||
return (SqmExpression<BigDecimal>) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<BigInteger> asBigInteger() {
|
||||
//noinspection unchecked
|
||||
return (SqmExpression<BigInteger>) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<String> asString() {
|
||||
//noinspection unchecked
|
||||
return (SqmExpression<String>) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> SqmExpression<X> as(Class<X> type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Static field reference [%s#%s] cannot be de-referenced",
|
||||
fieldOwnerJavaTypeDescriptor.getJavaType().getName(),
|
||||
fieldName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new SemanticException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Static field reference [%s#%s] cannot be de-referenced",
|
||||
fieldOwnerJavaTypeDescriptor.getJavaType().getName(),
|
||||
fieldName
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isCompoundSelection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends JpaSelection<?>> getSelectionItems() {
|
||||
// per-JPA
|
||||
throw new IllegalStateException( "Not a compound selection" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaSelection<T> alias(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlias() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -6,15 +6,19 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
import org.hibernate.query.sqm.consume.spi.SemanticQueryWalker;
|
||||
import org.hibernate.sql.ast.produce.metamodel.spi.EntityValuedExpressableType;
|
||||
import org.hibernate.sql.ast.produce.metamodel.spi.ExpressableType;
|
||||
import org.hibernate.query.hql.HqlInterpretationException;
|
||||
import org.hibernate.query.sqm.produce.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.spi.DomainResultProducer;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Represents an reference to an entity type as a literal. This is the JPA
|
||||
|
@ -25,26 +29,28 @@ import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptor;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmLiteralEntityType<T> extends AbstractSqmExpression<T> implements DomainResultProducer {
|
||||
private final EntityValuedExpressableType<T> entityType;
|
||||
public class SqmLiteralEntityType<T>
|
||||
extends AbstractSqmExpression<T>
|
||||
implements DomainResultProducer, SemanticPathPart {
|
||||
private final EntityDomainType<T> entityType;
|
||||
|
||||
public SqmLiteralEntityType(EntityValuedExpressableType<T> entityType, NodeBuilder nodeBuilder) {
|
||||
public SqmLiteralEntityType(EntityDomainType<T> entityType, NodeBuilder nodeBuilder) {
|
||||
super( entityType, nodeBuilder );
|
||||
this.entityType = entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<T> getJavaTypeDescriptor() {
|
||||
return getNodeType().getJavaTypeDescriptor();
|
||||
return getNodeType().getExpressableJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityValuedExpressableType<T> getNodeType() {
|
||||
public EntityDomainType<T> getNodeType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalApplyInferableType(ExpressableType<?> type) {
|
||||
public void internalApplyInferableType(SqmExpressable<?> type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,4 +71,20 @@ public class SqmLiteralEntityType<T> extends AbstractSqmExpression<T> implements
|
|||
public String asLoggableText() {
|
||||
return "TYPE(" + entityType + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemanticPathPart resolvePathPart(
|
||||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new HqlInterpretationException( "Cannot dereference an entity name" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath resolveIndexedAccess(
|
||||
SqmExpression selector,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
throw new HqlInterpretationException( "Cannot dereference an entity name" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.SQLQuery;
|
||||
|
@ -30,7 +29,7 @@ import org.hibernate.dialect.AbstractHANADialect;
|
|||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.MySQL5Dialect;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.spi.NamedSQLQueryDefinitionBuilder;
|
||||
import org.hibernate.boot.spi.NamedNativeQueryMementoBuilder;
|
||||
import org.hibernate.transform.BasicTransformerAdapter;
|
||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
||||
import org.hibernate.transform.Transformers;
|
||||
|
@ -155,7 +154,7 @@ public class NativeSQLQueriesTest extends BaseCoreFunctionalTestCase {
|
|||
@Test
|
||||
public void testRegisteredNamedSQLQueryWithScalar()
|
||||
{
|
||||
final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder();
|
||||
final NamedNativeQueryMementoBuilder builder = new NamedNativeQueryMementoBuilder();
|
||||
builder.setName("namedQuery");
|
||||
builder.setQuery("select count(*) AS c from ORGANIZATION");
|
||||
builder.setQueryReturns(new NativeSQLQueryReturn[1]);
|
||||
|
|
Loading…
Reference in New Issue