Support for JPA `SqlResultSetMapping`, both in terms of:

- creating memento instances for each mapping and storing into repository for runtime access
- applying to native-queries

Only support for column results is implemented atm since only scalar results are implemented for native-query
This commit is contained in:
Steve Ebersole 2020-07-29 11:58:27 -05:00
parent bbe3a6b0ad
commit 704896614d
45 changed files with 1055 additions and 549 deletions

View File

@ -0,0 +1,21 @@
/*
* 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;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class BootLogging {
public static final String NAME = "org.hibernate.orm.boot";
public static final Logger LOGGER = Logger.getLogger( NAME );
public static final boolean DEBUG_ENABLED = LOGGER.isDebugEnabled();
public static final boolean TRACE_ENABLED = LOGGER.isTraceEnabled();
}

View File

@ -14,10 +14,10 @@ import org.hibernate.SessionFactory;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.spi.NamedHqlQueryDefinition;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.spi.NamedProcedureCallDefinition;
import org.hibernate.boot.spi.NamedResultSetMappingDefinition;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.Mapping;

View File

@ -58,10 +58,10 @@ import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.boot.spi.NamedHqlQueryDefinition;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.spi.NamedProcedureCallDefinition;
import org.hibernate.boot.spi.NamedResultSetMappingDefinition;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder;
import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AvailableSettings;

View File

@ -24,17 +24,16 @@ import org.hibernate.SessionFactory;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.model.TypeDefinitionRegistry;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.NamedHqlQueryDefinition;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.spi.NamedProcedureCallDefinition;
import org.hibernate.boot.spi.NamedResultSetMappingDefinition;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
import org.hibernate.boot.spi.SessionFactoryBuilderFactory;
import org.hibernate.boot.spi.SessionFactoryBuilderImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderService;

View File

@ -12,7 +12,7 @@ import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.spi.AbstractNamedQueryDefinition;
import org.hibernate.boot.spi.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;

View File

@ -13,7 +13,7 @@ import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.AbstractNamedQueryDefinition;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.query.sql.internal.NamedNativeQueryMementoImpl;

View File

@ -17,7 +17,7 @@ import javax.persistence.StoredProcedureParameter;
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.spi.NamedProcedureCallDefinition;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.annotations.QueryHintDefinition;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;

View File

@ -28,7 +28,7 @@ import org.hibernate.boot.model.source.spi.MetadataSourceProcessor;
import org.hibernate.boot.model.source.spi.ToolingHintContext;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.boot.spi.HbmResultSetMappingDefinition;
import org.hibernate.boot.query.HbmResultSetMappingDefinition;
import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MappingDefaults;
import org.hibernate.boot.spi.MetadataBuildingContext;

View File

@ -17,9 +17,10 @@ import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryReturnType;
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.boot.spi.HbmResultSetMappingDefinition;
import org.hibernate.boot.spi.NamedHqlQueryDefinition;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.query.HbmResultSetMappingDefinition;
import org.hibernate.boot.query.HbmResultSetMappingDefinitionBuilder;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinitionBuilder;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.internal.util.StringHelper;
@ -103,7 +104,7 @@ public class NamedQueryBinder {
final String registrationName = prefix + namedQueryBinding.getName();
final NamedNativeQueryDefinition.Builder builder = new NamedNativeQueryDefinition.Builder( registrationName )
final NamedNativeQueryDefinitionBuilder builder = new NamedNativeQueryDefinitionBuilder( registrationName )
.setComment( namedQueryBinding.getComment() )
.setCacheable( namedQueryBinding.isCacheable() )
.setCacheMode( namedQueryBinding.getCacheMode() )
@ -114,7 +115,7 @@ public class NamedQueryBinder {
.setFetchSize( namedQueryBinding.getFetchSize() )
.setResultSetMappingName( namedQueryBinding.getResultsetRef() );
final HbmResultSetMappingDefinition.Builder implicitResultSetMappingBuilder = new HbmResultSetMappingDefinition.Builder( registrationName );
final HbmResultSetMappingDefinitionBuilder implicitResultSetMappingBuilder = new HbmResultSetMappingDefinitionBuilder( registrationName );
boolean foundQuery = false;
@ -160,8 +161,8 @@ public class NamedQueryBinder {
private static boolean processNamedQueryContentItem(
Object content,
NamedNativeQueryDefinition.Builder queryBuilder,
HbmResultSetMappingDefinition.Builder implicitResultSetMappingBuilder,
NamedNativeQueryDefinitionBuilder queryBuilder,
HbmResultSetMappingDefinitionBuilder implicitResultSetMappingBuilder,
JaxbHbmNamedNativeQueryType namedQueryBinding,
HbmLocalMetadataBuildingContext context) {
if ( content instanceof String ) {

View File

@ -24,7 +24,8 @@ import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryReturnType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType;
import org.hibernate.boot.jaxb.hbm.spi.NativeQueryNonScalarRootReturn;
import org.hibernate.boot.jaxb.hbm.spi.ResultSetMappingBindingDefinition;
import org.hibernate.boot.spi.HbmResultSetMappingDefinition;
import org.hibernate.boot.query.HbmResultSetMappingDefinition;
import org.hibernate.boot.query.HbmResultSetMappingDefinitionBuilder;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryCollectionReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryJoinReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
@ -62,7 +63,7 @@ public abstract class ResultSetMappingBinder {
throw new MappingException( "ResultSet mapping did not specify name", context.getOrigin() );
}
final HbmResultSetMappingDefinition.Builder builder = new HbmResultSetMappingDefinition.Builder( resultSetMappingSource.getName() );
final HbmResultSetMappingDefinitionBuilder builder = new HbmResultSetMappingDefinitionBuilder( resultSetMappingSource.getName() );
for ( Object valueMappingSource : resultSetMappingSource.getValueMappingSources() ) {
if ( valueMappingSource instanceof JaxbHbmNativeQueryReturnType ) {

View File

@ -0,0 +1,148 @@
/*
* 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.query;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
/**
* @author Steve Ebersole
*/
public abstract class AbstractNamedQueryBuilder<T extends AbstractNamedQueryBuilder<T>> {
private final String name;
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 AbstractNamedQueryBuilder(String name) {
this.name = name;
}
public String getName() {
return name;
}
protected abstract T 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 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 void addHint(String name, Object value) {
if ( hints == null ) {
hints = new HashMap<>();
}
hints.put( name, value );
}
public T addHints(Map<String, Object> hintsMap) {
if ( hints == null ) {
hints = new HashMap<>();
}
hints.putAll( hintsMap );
return getThis();
}
public Map<String, Object> getHints() {
return hints;
}
}

View File

@ -0,0 +1,179 @@
/*
* 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.query;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.Builders;
import org.hibernate.query.results.ScalarResultBuilder;
import org.hibernate.type.BasicType;
/**
* Boot-time descriptor of a result-set-mapping as defined in an `hbm.xml` file
* either implicitly or explicitly
*
* @see org.hibernate.Session#createNativeQuery(String, String)
* @see org.hibernate.Session#createStoredProcedureCall(String, String[])
* @see org.hibernate.Session#createStoredProcedureCall(String, String[])
*
* @author Steve Ebersole
*/
public class HbmResultSetMappingDefinition implements NamedResultSetMappingDefinition {
// todo (6.0) : see note on org.hibernate.boot.query.SqlResultSetMappingDefinition
private final String registrationName;
private final ResultMapping rootEntityReturn;
private final ResultMapping rootCollectionReturn;
private final List<ResultMapping> joinReturns;
private final List<ScalarMappingDefinition> scalarResultMappings;
public HbmResultSetMappingDefinition(
String registrationName,
ResultMapping rootEntityReturn,
ResultMapping rootCollectionReturn,
List<ResultMapping> joinReturns,
List<ScalarMappingDefinition> scalarResultMappings) {
this.registrationName = registrationName;
this.rootEntityReturn = rootEntityReturn;
this.rootCollectionReturn = rootCollectionReturn;
this.joinReturns = joinReturns;
this.scalarResultMappings = scalarResultMappings;
}
@Override
public String getRegistrationName() {
return registrationName;
}
@Override
public NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory) {
final List<ScalarResultBuilder> scalarResultBuilders;
if ( scalarResultMappings == null || scalarResultMappings.isEmpty() ) {
scalarResultBuilders = null;
}
else {
scalarResultBuilders = new ArrayList<>( scalarResultMappings.size() );
scalarResultMappings.forEach(
resultMapping -> {
scalarResultBuilders.add( resultMapping.resolve( factory ) );
}
);
}
throw new NotYetImplementedFor6Exception( getClass() );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// `hbm.xml` returns
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryReturnType
*/
public interface RootEntityMappingDefinition extends ResultMapping {
String getEntityName();
String getSqlAlias();
List<HbmPropertyMappingDefinition> getProperties();
String getDiscriminatorColumnName();
LockMode getLockMode();
}
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryPropertyReturnType
*/
public interface HbmPropertyMappingDefinition extends ResultMapping {
String getPropertyPath();
List<String> getColumnNames();
}
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryJoinReturnType
*/
public interface JoinMappingDefinition extends ResultMapping {
String getJoinedPropertyPath();
String getSqlAlias();
List<HbmPropertyMappingDefinition> getProperties();
LockMode getLockMode();
}
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryCollectionLoadReturnType
*/
public interface RootCollectionMappingDefinition extends ResultMapping {
String getCollectionRole();
String getSqlAlias();
List<HbmPropertyMappingDefinition> getProperties();
LockMode getLockMode();
}
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType
*/
public static class ScalarMappingDefinition implements ResultMapping {
private final String columnName;
private final String hibernateTypeName;
public ScalarMappingDefinition(String columnName, String hibernateTypeName) {
this.columnName = columnName;
this.hibernateTypeName = hibernateTypeName;
}
public String getColumnName() {
return columnName;
}
public String getHibernateTypeName() {
return hibernateTypeName;
}
@Override
public ScalarResultBuilder resolve(SessionFactoryImplementor factory) {
if ( hibernateTypeName != null ) {
final BasicType<?> namedType = factory.getTypeConfiguration()
.getBasicTypeRegistry()
.getRegisteredType( hibernateTypeName );
if ( namedType == null ) {
throw new IllegalArgumentException( "Could not resolve named type : " + hibernateTypeName );
}
return Builders.scalar( columnName );
}
// todo (6.0) : column name may be optional in HBM - double check
return Builders.scalar( columnName );
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA returns
/**
* @see javax.persistence.ColumnResult
*/
interface JpaColumnResult {
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.query;
import java.util.List;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryCollectionLoadReturnType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryJoinReturnType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryReturnType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType;
import org.hibernate.boot.model.source.internal.hbm.HbmLocalMetadataBuildingContext;
/**
* @author Steve Ebersole
*/
public class HbmResultSetMappingDefinitionBuilder {
private final String registrationName;
private NamedResultSetMappingDefinition.ResultMapping rootEntityReturn;
private NamedResultSetMappingDefinition.ResultMapping rootCollectionReturn;
private List<NamedResultSetMappingDefinition.ResultMapping> joinReturns;
private List<HbmResultSetMappingDefinition.ScalarMappingDefinition> rootScalarReturns;
public HbmResultSetMappingDefinitionBuilder(String queryRegistrationName) {
this.registrationName = queryRegistrationName;
}
public String getRegistrationName() {
return registrationName;
}
public HbmResultSetMappingDefinitionBuilder addReturn(JaxbHbmNativeQueryScalarReturnType returnMapping) {
rootScalarReturns.add(
new HbmResultSetMappingDefinition.ScalarMappingDefinition(
returnMapping.getColumn(),
returnMapping.getType()
)
);
return this;
}
public HbmResultSetMappingDefinitionBuilder addReturn(JaxbHbmNativeQueryReturnType returnMapping) {
throw new NotYetImplementedFor6Exception();
}
public void addReturn(JaxbHbmNativeQueryJoinReturnType returnMapping) {
throw new NotYetImplementedFor6Exception();
}
public void addReturn(JaxbHbmNativeQueryCollectionLoadReturnType returnMapping) {
throw new NotYetImplementedFor6Exception();
}
public boolean hasAnyReturns() {
return rootEntityReturn != null || rootCollectionReturn != null || rootScalarReturns != null;
}
public HbmResultSetMappingDefinition build(HbmLocalMetadataBuildingContext context) {
if ( rootCollectionReturn != null
&& ( rootEntityReturn != null || rootScalarReturns != null ) ) {
throw new MappingException(
"HBM return-collection ResultSet mapping cannot define an entity or scalar returns : " + registrationName,
context.getOrigin()
);
}
if ( joinReturns != null ) {
if ( rootEntityReturn == null && rootCollectionReturn == null ) {
throw new MappingException(
"HBM return-join ResultSet mapping must be used in conjunction with root entity or collection return : " + registrationName,
context.getOrigin()
);
}
}
return new HbmResultSetMappingDefinition(
registrationName,
rootEntityReturn,
rootCollectionReturn,
joinReturns,
rootScalarReturns
);
}
}

View File

@ -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.boot.spi;
package org.hibernate.boot.query;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.internal.NamedCallableQueryMementoImpl;

View File

@ -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.boot.spi;
package org.hibernate.boot.query;
import java.util.HashMap;
import java.util.Map;
@ -29,7 +29,7 @@ public interface NamedHqlQueryDefinition extends NamedQueryDefinition {
@Override
NamedHqlQueryMemento resolve(SessionFactoryImplementor factory);
class Builder extends AbstractNamedQueryDefinition.AbstractBuilder<Builder> {
class Builder extends AbstractNamedQueryBuilder<Builder> {
private String hqlString;
private Integer firstResult;

View File

@ -0,0 +1,38 @@
/*
* 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.query;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.hibernate.boot.internal.NamedNativeQueryDefinitionImpl;
import org.hibernate.boot.spi.AbstractNamedQueryDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
/**
* Boot-time descriptor of a named native query, as defined in
* annotations or xml
*
* @see javax.persistence.NamedNativeQuery
* @see org.hibernate.annotations.NamedNativeQuery
*
* @author Steve Ebersole
* @author Gavin King
*/
public interface NamedNativeQueryDefinition extends NamedQueryDefinition {
String getSqlQueryString();
String getResultSetMappingName();
String getResultSetMappingClassName();
@Override
NamedNativeQueryMemento resolve(SessionFactoryImplementor factory);
}

View File

@ -0,0 +1,158 @@
/*
* 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.query;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.internal.NamedNativeQueryDefinitionImpl;
/**
* @author Steve Ebersole
*/
public class NamedNativeQueryDefinitionBuilder extends AbstractNamedQueryBuilder<NamedNativeQueryDefinitionBuilder> {
private String sqlString;
private String resultSetMappingName;
private String resultSetMappingClassName;
private Set<String> querySpaces;
private Map<String, String> parameterTypes;
public NamedNativeQueryDefinitionBuilder(String name) {
super( name );
}
public NamedNativeQueryDefinitionBuilder setSqlString(String sqlString) {
this.sqlString = sqlString;
return getThis();
}
public NamedNativeQueryDefinition build() {
return new NamedNativeQueryDefinitionImpl(
getName(),
sqlString,
resultSetMappingName,
resultSetMappingClassName,
getQuerySpaces(),
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
getTimeout(),
getFetchSize(),
getComment(),
getHints()
);
}
@Override
protected NamedNativeQueryDefinitionBuilder getThis() {
return this;
}
public Set<String> getQuerySpaces() {
return querySpaces;
}
public NamedNativeQueryDefinitionBuilder addSynchronizedQuerySpaces(Set<String> querySpaces) {
if ( querySpaces == null || querySpaces.isEmpty() ) {
return this;
}
if ( this.querySpaces == null ) {
this.querySpaces = new HashSet<>();
}
this.querySpaces.addAll( querySpaces );
return getThis();
}
public NamedNativeQueryDefinitionBuilder addSynchronizedQuerySpace(String space) {
if ( this.querySpaces == null ) {
this.querySpaces = new HashSet<>();
}
this.querySpaces.add( space );
return getThis();
}
public NamedNativeQueryDefinitionBuilder setQuerySpaces(Set<String> spaces) {
this.querySpaces = spaces;
return this;
}
public NamedNativeQueryDefinitionBuilder setResultSetMappingName(String resultSetMappingName) {
this.resultSetMappingName = resultSetMappingName;
return this;
}
public NamedNativeQueryDefinitionBuilder setResultSetMappingClassName(String resultSetMappingClassName) {
this.resultSetMappingClassName = resultSetMappingClassName;
return this;
}
@Override
public NamedNativeQueryDefinitionBuilder setFetchSize(Integer fetchSize) {
return (NamedNativeQueryDefinitionBuilder) super.setFetchSize( fetchSize );
}
@Override
public NamedNativeQueryDefinitionBuilder setCacheable(Boolean cacheable) {
return (NamedNativeQueryDefinitionBuilder) super.setCacheable( cacheable );
}
@Override
public NamedNativeQueryDefinitionBuilder setCacheRegion(String cacheRegion) {
return (NamedNativeQueryDefinitionBuilder) super.setCacheRegion( cacheRegion );
}
@Override
public NamedNativeQueryDefinitionBuilder setCacheMode(CacheMode cacheMode) {
return (NamedNativeQueryDefinitionBuilder) super.setCacheMode( cacheMode );
}
@Override
public NamedNativeQueryDefinitionBuilder setLockOptions(LockOptions lockOptions) {
return (NamedNativeQueryDefinitionBuilder) super.setLockOptions( lockOptions );
}
@Override
public NamedNativeQueryDefinitionBuilder setTimeout(Integer timeout) {
return (NamedNativeQueryDefinitionBuilder) super.setTimeout( timeout );
}
@Override
public NamedNativeQueryDefinitionBuilder setFlushMode(FlushMode flushMode) {
return (NamedNativeQueryDefinitionBuilder) super.setFlushMode( flushMode );
}
@Override
public NamedNativeQueryDefinitionBuilder setReadOnly(Boolean readOnly) {
return (NamedNativeQueryDefinitionBuilder) super.setReadOnly( readOnly );
}
@Override
public NamedNativeQueryDefinitionBuilder setComment(String comment) {
return (NamedNativeQueryDefinitionBuilder) super.setComment( comment );
}
public void addParameterTypeHint(String name, String type) {
if ( parameterTypes == null ) {
parameterTypes = new HashMap<>();
}
parameterTypes.put( name, type );
}
}

View File

@ -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.boot.spi;
package org.hibernate.boot.query;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;

View File

@ -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.boot.spi;
package org.hibernate.boot.query;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.named.NamedQueryMemento;

View File

@ -4,12 +4,20 @@
* 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;
package org.hibernate.boot.query;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.ResultBuilder;
/**
* Models the "boot view" of a ResultSet mapping used in the mapping
* of native and procedure queries.
*
* Ultimately used to generate a NamedResultSetMappingMemento that is
* stored in the {@link org.hibernate.query.named.NamedQueryRepository}
* for availability at runtime
*
* @author Steve Ebersole
*/
public interface NamedResultSetMappingDefinition {
@ -18,6 +26,13 @@ public interface NamedResultSetMappingDefinition {
*/
String getRegistrationName();
/**
* Contract for the individual result mappings
*/
interface ResultMapping {
ResultBuilder resolve(SessionFactoryImplementor factory);
}
/**
* Create the named runtime memento instance
*/

View File

@ -0,0 +1,154 @@
/*
* 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.query;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.ColumnResult;
import javax.persistence.SqlResultSetMapping;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.BootLogging;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.ScalarResultBuilder;
import org.hibernate.query.results.StandardScalarResultBuilder;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefinition {
// todo (6.0) : we can probably reuse the NamedResultSetMappingDefinition
// implementation between HBM and annotation handling. We'd
// just need different "builders" for each source and handle the
// variances in those builders. But once we have a
// NamedResultSetMappingDefinition and all of its sub-parts,
// resolving to a memento is the same
// -
// additionally, consider having the sub-parts (the return
// representations) be what is used and handed to the
// NamedResultSetMappingMemento directly. They simply need
// to be capable of resolving themselves into ResultBuilders
// (`org.hibernate.query.results.ResultBuilder`) as part of the
// memento for its resolution
public static SqlResultSetMappingDefinition from(
SqlResultSetMapping mappingAnnotation,
MetadataBuildingContext context) {
if ( mappingAnnotation.classes().length > 0 ) {
throw new NotYetImplementedFor6Exception(
"Support for dynamic-instantiation result mappings not yet implemented"
);
}
if ( mappingAnnotation.entities().length > 0 ) {
throw new NotYetImplementedFor6Exception(
"Support for entity result mappings not yet implemented"
);
}
if ( mappingAnnotation.columns().length == 0 ) {
throw new NotYetImplementedFor6Exception( "Should never get here" );
}
final List<JpaColumnResultMapping> columnResultMappings;
if ( mappingAnnotation.columns().length == 0 ) {
columnResultMappings = null;
}
else {
columnResultMappings = new ArrayList<>( mappingAnnotation.columns().length );
for ( int i = 0; i < mappingAnnotation.columns().length; i++ ) {
final ColumnResult columnMapping = mappingAnnotation.columns()[i];
columnResultMappings.add(
new JpaColumnResultMapping( columnMapping.name(), columnMapping.type() )
);
}
}
return new SqlResultSetMappingDefinition(
mappingAnnotation.name(),
columnResultMappings,
context
);
}
private final String mappingName;
private final List<JpaColumnResultMapping> columnResultMappings;
private SqlResultSetMappingDefinition(
String mappingName,
List<JpaColumnResultMapping> columnResultMappings,
MetadataBuildingContext context) {
this.mappingName = mappingName;
this.columnResultMappings = columnResultMappings;
}
@Override
public String getRegistrationName() {
return mappingName;
}
@Override
public NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory) {
final List<ScalarResultBuilder> scalarResultBuilders = new ArrayList<>();
for ( int i = 0; i < columnResultMappings.size(); i++ ) {
final JpaColumnResultMapping resultMapping = columnResultMappings.get( i );
scalarResultBuilders.add( resultMapping.resolve( factory ) );
}
return new NamedResultSetMappingMementoImpl(
mappingName,
scalarResultBuilders,
factory
);
}
/**
* @see javax.persistence.ColumnResult
*/
private static class JpaColumnResultMapping implements ResultMapping {
private final String columnName;
private final Class<?> explicitJavaType;
public JpaColumnResultMapping(String columnName, Class<?> explicitJavaType) {
this.columnName = columnName;
this.explicitJavaType = explicitJavaType == void.class
? null
: explicitJavaType;
}
public String getColumnName() {
return columnName;
}
public Class<?> getExplicitJavaType() {
return explicitJavaType;
}
@Override
public ScalarResultBuilder resolve(SessionFactoryImplementor factory) {
if ( explicitJavaType != null ) {
final JavaTypeDescriptor<?> jtd = factory.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.getDescriptor( explicitJavaType );
BootLogging.LOGGER.debugf( "ColumnResult explicit type resolved to : " + jtd );
return new StandardScalarResultBuilder( columnName, jtd );
}
return new StandardScalarResultBuilder( columnName );
}
}
}

View File

@ -18,6 +18,10 @@ import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.TypeDefinition;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;

View File

@ -12,6 +12,7 @@ import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.query.NamedQueryDefinition;
/**
* @author Steve Ebersole
@ -105,134 +106,4 @@ public abstract class AbstractNamedQueryDefinition implements NamedQueryDefiniti
return hints;
}
protected static abstract class AbstractBuilder<T extends AbstractBuilder> {
private final String name;
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 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 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 void addHint(String name, Object value) {
if ( hints == null ) {
hints = new HashMap<>();
}
hints.put( name, value );
}
public T addHints(Map<String, Object> hintsMap) {
if ( hints == null ) {
hints = new HashMap<>();
}
hints.putAll( hintsMap );
return getThis();
}
public Map<String, Object> getHints() {
return hints;
}
}
}

View File

@ -1,160 +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.boot.spi;
import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryCollectionLoadReturnType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryJoinReturnType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryReturnType;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType;
import org.hibernate.boot.model.source.internal.hbm.HbmLocalMetadataBuildingContext;
/**
* Boot-time descriptor of a result-set-mapping as defined in an `hbm.xml` file
* either implicitly or explicitly
*
* @see org.hibernate.Session#createNativeQuery(String, String)
* @see org.hibernate.Session#createStoredProcedureCall(String, String[])
* @see org.hibernate.Session#createStoredProcedureCall(String, String[])
*
* @author Steve Ebersole
*/
public interface HbmResultSetMappingDefinition extends NamedResultSetMappingDefinition {
class Builder {
private final String registrationName;
private RootEntityMappingDefinition rootEntityReturn;
private RootCollectionMappingDefinition rootCollectionReturn;
private List<JoinMappingDefinition> joinReturns;
private List<ScalarMappingDefinition> rootScalarReturns;
public Builder(String queryRegistrationName) {
this.registrationName = queryRegistrationName;
}
public String getRegistrationName() {
return registrationName;
}
public Builder addReturn(JaxbHbmNativeQueryScalarReturnType returnMapping) {
throw new NotYetImplementedFor6Exception();
}
public Builder addReturn(JaxbHbmNativeQueryReturnType returnMapping) {
throw new NotYetImplementedFor6Exception();
}
public void addReturn(JaxbHbmNativeQueryJoinReturnType returnMapping) {
throw new NotYetImplementedFor6Exception();
}
public void addReturn(JaxbHbmNativeQueryCollectionLoadReturnType returnMapping) {
throw new NotYetImplementedFor6Exception();
}
public boolean hasAnyReturns() {
return rootEntityReturn != null || rootCollectionReturn != null || rootScalarReturns != null;
}
public HbmResultSetMappingDefinition build(HbmLocalMetadataBuildingContext context) {
if ( rootCollectionReturn != null
&& ( rootEntityReturn != null || rootScalarReturns != null ) ) {
throw new MappingException(
"HBM return-collection ResultSet mapping cannot define an entity or scalar returns : " + registrationName,
context.getOrigin()
);
}
if ( joinReturns != null ) {
if ( rootEntityReturn == null && rootCollectionReturn == null ) {
throw new MappingException(
"HBM return-join ResultSet mapping must be used in conjunction with root entity or collection return : " + registrationName,
context.getOrigin()
);
}
}
throw new NotYetImplementedFor6Exception();
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// `hbm.xml` returns
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryReturnType
*/
interface RootEntityMappingDefinition {
String getEntityName();
String getSqlAlias();
List<HbmPropertyMappingDefinition> getProperties();
String getDiscriminatorColumnName();
LockMode getLockMode();
}
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryPropertyReturnType
*/
interface HbmPropertyMappingDefinition {
String getPropertyPath();
List<String> getColumnNames();
}
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryJoinReturnType
*/
interface JoinMappingDefinition {
String getJoinedPropertyPath();
String getSqlAlias();
List<HbmPropertyMappingDefinition> getProperties();
LockMode getLockMode();
}
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryCollectionLoadReturnType
*/
interface RootCollectionMappingDefinition {
String getCollectionRole();
String getSqlAlias();
List<HbmPropertyMappingDefinition> getProperties();
LockMode getLockMode();
}
/**
* @see org.hibernate.boot.jaxb.hbm.spi.JaxbHbmNativeQueryScalarReturnType
*/
interface ScalarMappingDefinition {
String getColumnName();
String getTypeName();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// JPA returns
/**
* @see javax.persistence.ColumnResult
*/
interface JpaColumnResult {
}
}

View File

@ -30,6 +30,10 @@ import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
import org.hibernate.boot.model.relational.QualifiedTableName;
import org.hibernate.boot.model.source.spi.LocalMetadataBuildingContext;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AttributeConverterDefinition;
import org.hibernate.cfg.JPAIndexHolder;

View File

@ -1,129 +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.boot.spi;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.hibernate.boot.internal.NamedNativeQueryDefinitionImpl;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.sql.spi.NamedNativeQueryMemento;
/**
* Boot-time descriptor of a named native query, as defined in
* annotations or xml
*
* @see javax.persistence.NamedNativeQuery
* @see org.hibernate.annotations.NamedNativeQuery
*
* @author Steve Ebersole
* @author Gavin King
*/
public interface NamedNativeQueryDefinition extends NamedQueryDefinition {
String getSqlQueryString();
String getResultSetMappingName();
String getResultSetMappingClassName();
@Override
NamedNativeQueryMemento resolve(SessionFactoryImplementor factory);
class Builder extends AbstractNamedQueryDefinition.AbstractBuilder<Builder> {
private String sqlString;
private String resultSetMappingName;
private String resultSetMappingClassName;
private Set<String> querySpaces;
private Map<String,String> parameterTypes;
public Builder(String name) {
super( name );
}
public Builder setSqlString(String sqlString) {
this.sqlString = sqlString;
return getThis();
}
public NamedNativeQueryDefinition build() {
return new NamedNativeQueryDefinitionImpl(
getName(),
sqlString,
resultSetMappingName,
resultSetMappingClassName,
getQuerySpaces(),
getCacheable(),
getCacheRegion(),
getCacheMode(),
getFlushMode(),
getReadOnly(),
getTimeout(),
getFetchSize(),
getComment(),
getHints()
);
}
@Override
protected Builder getThis() {
return this;
}
public Set<String> getQuerySpaces() {
return querySpaces;
}
public Builder addSynchronizedQuerySpaces(Set<String> querySpaces) {
if ( querySpaces == null || querySpaces.isEmpty() ) {
return this;
}
if ( this.querySpaces == null ) {
this.querySpaces = new HashSet<>();
}
this.querySpaces.addAll( querySpaces );
return getThis();
}
public Builder addSynchronizedQuerySpace(String space) {
if ( this.querySpaces == null ) {
this.querySpaces = new HashSet<>();
}
this.querySpaces.add( space );
return getThis();
}
public Builder setQuerySpaces(Set<String> spaces) {
this.querySpaces = spaces;
return this;
}
public Builder setResultSetMappingName(String resultSetMappingName) {
this.resultSetMappingName = resultSetMappingName;
return this;
}
public Builder setResultSetMappingClassName(String resultSetMappingClassName) {
this.resultSetMappingClassName = resultSetMappingClassName;
return this;
}
public void addParameterTypeHint(String name, String type) {
if ( parameterTypes == null ) {
parameterTypes = new HashMap<>();
}
parameterTypes.put( name, type );
}
}
}

View File

@ -43,10 +43,10 @@ import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.spi.NamedHqlQueryDefinition;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.spi.NamedProcedureCallDefinition;
import org.hibernate.boot.spi.NamedResultSetMappingDefinition;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedProcedureCallDefinition;
import org.hibernate.boot.query.NamedResultSetMappingDefinition;
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.internal.CoreLogging;

View File

@ -23,10 +23,10 @@ import org.hibernate.annotations.CacheModeType;
import org.hibernate.annotations.FlushModeType;
import org.hibernate.annotations.QueryHints;
import org.hibernate.boot.internal.NamedHqlQueryDefinitionImpl;
import org.hibernate.boot.internal.NamedNativeQueryDefinitionImpl;
import org.hibernate.boot.query.NamedNativeQueryDefinitionBuilder;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.NamedHqlQueryDefinition;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.cfg.BinderHelper;
import org.hibernate.internal.CoreMessageLogger;
@ -105,7 +105,7 @@ public abstract class QueryBinder {
? null
: queryAnn.resultClass().getName();
final NamedNativeQueryDefinition.Builder builder = new NamedNativeQueryDefinitionImpl.Builder( registrationName )
final NamedNativeQueryDefinitionBuilder builder = new NamedNativeQueryDefinitionBuilder( registrationName )
.setSqlString( queryString )
.setResultSetMappingName( resultSetMappingName )
.setResultSetMappingClassName( resultSetMappingClassName )
@ -154,7 +154,7 @@ public abstract class QueryBinder {
? null
: queryAnn.resultClass().getName();
final NamedNativeQueryDefinition.Builder builder = new NamedNativeQueryDefinitionImpl.Builder( registrationName )
final NamedNativeQueryDefinitionBuilder builder = new NamedNativeQueryDefinitionBuilder( registrationName )
.setSqlString( queryAnn.query() )
.setResultSetMappingName( resultSetMappingName )
.setResultSetMappingClassName( resultSetMappingClassName )

View File

@ -22,6 +22,7 @@ import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
import org.hibernate.boot.query.SqlResultSetMappingDefinition;
/**
* @author Emmanuel Bernard

View File

@ -1,42 +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.cfg.annotations;
import javax.persistence.SqlResultSetMapping;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.NamedResultSetMappingDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.internal.NamedResultSetMappingMementoImpl;
import org.hibernate.query.named.NamedResultSetMappingMemento;
/**
* @author Steve Ebersole
*/
public class SqlResultSetMappingDefinition implements NamedResultSetMappingDefinition {
public static SqlResultSetMappingDefinition from(
SqlResultSetMapping mappingAnnotation,
MetadataBuildingContext context) {
return new SqlResultSetMappingDefinition( mappingAnnotation.name(), context );
}
private final String mappingName;
private SqlResultSetMappingDefinition(String mappingName, MetadataBuildingContext context) {
this.mappingName = mappingName;
}
@Override
public String getRegistrationName() {
return mappingName;
}
@Override
public NamedResultSetMappingMemento resolve(SessionFactoryImplementor factory) {
return new NamedResultSetMappingMementoImpl( mappingName, factory );
}
}

View File

@ -517,8 +517,8 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
}
@Override
public NativeQueryImplementor createNativeQuery(String sqlString, String resultSetMapping) {
return delegate.createNativeQuery( sqlString, resultSetMapping );
public NativeQueryImplementor createNativeQuery(String sqlString, String resultSetMappingName) {
return delegate.createNativeQuery( sqlString, resultSetMappingName );
}
@Override

View File

@ -102,7 +102,7 @@ public interface SessionImplementor extends Session, SharedSessionContractImplem
NativeQueryImplementor createNativeQuery(String sqlString, Class resultClass);
@Override
NativeQueryImplementor createNativeQuery(String sqlString, String resultSetMapping);
NativeQueryImplementor createNativeQuery(String sqlString, String resultSetMappingName);
@Override
NativeQueryImplementor getNamedNativeQuery(String name);

View File

@ -51,6 +51,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.transaction.internal.TransactionImpl;
import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.id.uuid.StandardRandomStrategy;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work;
import org.hibernate.jdbc.WorkExecutorVisitable;
@ -62,6 +63,7 @@ import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.Query;
import org.hibernate.query.hql.spi.HqlQueryImplementor;
import org.hibernate.query.hql.spi.NamedHqlQueryMemento;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.QueryInterpretationCache;
@ -690,34 +692,34 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
}
@Override
public NativeQueryImplementor createNativeQuery(String sqlString, String resultSetMapping) {
// checkOpen();
// pulseTransactionCoordinator();
// delayedAfterCompletion();
//
// final NativeQueryImplementor query;
// try {
// if ( StringHelper.isNotEmpty( resultSetMapping ) ) {
// final ResultSetMappingDescriptor resultSetMappingDescriptor = getFactory().getQueryEngine()
// .getNamedQueryRepository()
// .getResultSetMappingDescriptor( resultSetMapping );
//
// if ( resultSetMappingDescriptor == null ) {
// throw new HibernateException( "Could not resolve specified result-set mapping name : " + resultSetMapping );
// }
//
// query = new NativeQueryImpl( sqlString, resultSetMappingDescriptor, this );
// }
// else {
// query = new NativeQueryImpl( sqlString, this );
// }
// }
// catch (RuntimeException he) {
// throw getExceptionConverter().convert( he );
// }
//
// return query;
throw new NotYetImplementedFor6Exception( getClass() );
public NativeQueryImplementor createNativeQuery(String sqlString, String resultSetMappingName) {
checkOpen();
pulseTransactionCoordinator();
delayedAfterCompletion();
final NativeQueryImplementor query;
try {
if ( StringHelper.isNotEmpty( resultSetMappingName ) ) {
final NamedResultSetMappingMemento resultSetMappingMemento = getFactory().getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( resultSetMappingName );
if ( resultSetMappingMemento == null ) {
throw new HibernateException( "Could not resolve specified result-set mapping name : " + resultSetMappingName );
}
query = new NativeQueryImpl( sqlString, resultSetMappingMemento, this );
}
else {
query = new NativeQueryImpl( sqlString, this );
}
}
catch (RuntimeException he) {
throw getExceptionConverter().convert( he );
}
return query;
// throw new NotYetImplementedFor6Exception( getClass() );
}

View File

@ -118,14 +118,14 @@ public interface QueryProducer {
* implicit mapping to the specified Java type.
*
* @param sqlString Native (SQL) query string
* @param resultSetMapping The explicit (named) result mapping
* @param resultSetMappingName The explicit result mapping name
*
* @return The NativeQuery instance for manipulation and execution
*
* @see javax.persistence.EntityManager#createNativeQuery(String,Class)
* @see javax.persistence.SqlResultSetMapping
*/
NativeQuery createNativeQuery(String sqlString, String resultSetMapping);
NativeQuery createNativeQuery(String sqlString, String resultSetMappingName);
/**
* Get a NativeQuery instance for a named native SQL query

View File

@ -10,7 +10,7 @@ import java.util.HashMap;
import java.util.Map;
import org.hibernate.LockOptions;
import org.hibernate.boot.spi.NamedHqlQueryDefinition;
import org.hibernate.boot.query.NamedHqlQueryDefinition;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.hql.internal.NamedHqlQueryMementoImpl;
import org.hibernate.query.named.AbstractNamedQueryMemento;

View File

@ -6,21 +6,30 @@
*/
package org.hibernate.query.internal;
import java.util.List;
import java.util.function.Consumer;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.ResultSetMapping;
import org.hibernate.query.results.ScalarResultBuilder;
/**
* Standard `NamedResultSetMappingMemento` implementation
*
* @author Steve Ebersole
*/
public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMemento {
private final String name;
public NamedResultSetMappingMementoImpl(String name, SessionFactoryImplementor factory) {
private final List<ScalarResultBuilder> scalarResultBuilders;
public NamedResultSetMappingMementoImpl(
String name,
List<ScalarResultBuilder> scalarResultBuilders,
SessionFactoryImplementor factory) {
this.name = name;
this.scalarResultBuilders = scalarResultBuilders;
}
@Override
@ -33,6 +42,16 @@ public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMe
ResultSetMapping resultSetMapping,
Consumer<String> querySpaceConsumer,
SessionFactoryImplementor sessionFactory) {
throw new NotYetImplementedFor6Exception( getClass() );
scalarResultBuilders.forEach(
builder -> resultSetMapping.addResultBuilder(
(jdbcResultsMetadata, legacyFetchResolver, sqlSelectionConsumer, sessionFactory1) ->
builder.buildReturn(
jdbcResultsMetadata,
legacyFetchResolver,
sqlSelectionConsumer,
sessionFactory
)
)
);
}
}

View File

@ -38,7 +38,7 @@ public class StandardScalarResultBuilder implements ScalarResultBuilder {
this.explicitJavaTypeDescriptor = null;
}
StandardScalarResultBuilder(String explicitName, BasicType<?> explicitType) {
public StandardScalarResultBuilder(String explicitName, BasicType<?> explicitType) {
assert explicitName != null;
this.explicitName = explicitName;
@ -48,7 +48,7 @@ public class StandardScalarResultBuilder implements ScalarResultBuilder {
this.explicitJavaTypeDescriptor = null;
}
StandardScalarResultBuilder(String explicitName, JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
public StandardScalarResultBuilder(String explicitName, JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
assert explicitName != null;
this.explicitName = explicitName;

View File

@ -52,7 +52,7 @@ public interface QueryProducerImplementor extends QueryProducer {
<R> NativeQueryImplementor<R> createNativeQuery(String sqlString, Class<R> resultClass);
@Override
NativeQueryImplementor createNativeQuery(String sqlString, String resultSetMapping);
NativeQueryImplementor createNativeQuery(String sqlString, String resultSetMappingName);
@Override
NativeQueryImplementor getNamedNativeQuery(String name);

View File

@ -44,6 +44,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.RootGraph;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.AbstractSharedSessionContract;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
@ -57,6 +58,7 @@ import org.hibernate.query.TupleTransformer;
import org.hibernate.query.internal.ParameterMetadataImpl;
import org.hibernate.query.internal.QueryOptionsImpl;
import org.hibernate.query.internal.QueryParameterBindingsImpl;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.results.Builders;
import org.hibernate.query.results.EntityResultBuilder;
import org.hibernate.query.results.LegacyFetchBuilder;
@ -159,6 +161,22 @@ public class NativeQueryImpl<R>
// todo (6.0) : relatedly, does `resultSetMappingName` come from `NamedNativeQuery#resultSetMapping`?
}
public NativeQueryImpl(
String sqlString,
NamedResultSetMappingMemento resultSetMappingMemento,
AbstractSharedSessionContract session) {
super( session );
this.sqlString = sqlString;
resultSetMappingMemento.resolve( resultSetMapping, (s) -> {}, getSessionFactory() );
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
}
private ParameterInterpretation resolveParameterInterpretation(SharedSessionContractImplementor session) {
final SessionFactoryImplementor sessionFactory = session.getFactory();
final QueryEngine queryEngine = sessionFactory.getQueryEngine();

View File

@ -9,7 +9,7 @@ package org.hibernate.query.sql.spi;
import java.util.Set;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.query.named.AbstractNamedQueryMemento;

View File

@ -19,6 +19,13 @@ import javax.persistence.SqlResultSetMapping;
name = "name",
columns = @ColumnResult( name = "name" )
)
@SqlResultSetMapping(
name = "id_name",
columns = {
@ColumnResult( name = "id" ),
@ColumnResult( name = "name" )
}
)
public class SimpleEntityWithNamedMappings {
@Id
private Integer id;

View File

@ -13,7 +13,6 @@ import org.hibernate.query.results.ResultSetMappingImpl;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
@ -28,8 +27,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
@SessionFactory
public class SimpleNamedMappingTests {
@Test
@FailureExpected( reason = "Memento-ization of row-reader not yet implemented" )
public void testMapping(SessionFactoryScope sessionFactoryScope) {
public void testMappingResolution(SessionFactoryScope sessionFactoryScope) {
final QueryEngine queryEngine = sessionFactoryScope.getSessionFactory().getQueryEngine();
final NamedQueryRepository namedQueryRepository = queryEngine.getNamedQueryRepository();
final NamedResultSetMappingMemento mappingMemento = namedQueryRepository.getResultSetMappingMemento( "name" );

View File

@ -0,0 +1,70 @@
/*
* 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.orm.test.query.named.resultmapping;
import java.time.Instant;
import org.hibernate.query.named.NamedResultSetMappingMemento;
import org.hibernate.query.sql.spi.NativeQueryImplementor;
import org.hibernate.testing.orm.domain.StandardDomainModel;
import org.hibernate.testing.orm.domain.helpdesk.Incident;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.notNullValue;
/**
* @author Steve Ebersole
*/
@DomainModel( standardModels = StandardDomainModel.HELPDESK )
@SessionFactory
public class UsageTests {
@Test
public void testSimpleScalarMappings(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
// make sure it is in the repository
final NamedResultSetMappingMemento mappingMemento = session.getSessionFactory()
.getQueryEngine()
.getNamedQueryRepository()
.getResultSetMappingMemento( "incident_summary" );
assertThat( mappingMemento, notNullValue() );
// apply it to a native-query
final String qryString = "select id, description, reported from incident";
session.createNativeQuery( qryString, "incident_summary" ).list();
// todo (6.0) : should also try executing the ProcedureCall once that functionality is implemented
session.createStoredProcedureCall( "abc", "incident_summary" );
}
);
}
@BeforeEach
public void prepareData(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.save( new Incident( 1, "test", Instant.now() ) );
}
);
}
@AfterEach
public void cleanUpData(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "delete Incident" ).executeUpdate();
}
);
}
}

View File

@ -8,10 +8,8 @@ import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.boot.spi.NamedNativeQueryDefinition;
import org.hibernate.boot.query.NamedNativeQueryDefinition;
import org.hibernate.engine.jdbc.ReaderInputStream;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;

View File

@ -7,21 +7,54 @@
package org.hibernate.testing.orm.domain.helpdesk;
import java.time.Instant;
import javax.persistence.ColumnResult;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.SqlResultSetMapping;
/**
* @author Steve Ebersole
*/
@Entity
@SqlResultSetMapping(
name = "incident_summary",
columns = {
@ColumnResult( name = "id" ),
@ColumnResult( name = "description" ),
@ColumnResult( name = "reported", type = Instant.class )
}
)
public class Incident {
private Integer id;
private String description;
private Instant reported;
private Instant effectiveStart;
private Instant effectiveEnd;
public Incident() {
}
public Incident(Integer id, String description, Instant reported) {
this.id = id;
this.description = description;
this.reported = reported;
}
public Incident(
Integer id,
String description,
Instant reported,
Instant effectiveStart,
Instant effectiveEnd) {
this.id = id;
this.description = description;
this.reported = reported;
this.effectiveStart = effectiveStart;
this.effectiveEnd = effectiveEnd;
}
@Id
public Integer getId() {
return id;
@ -31,6 +64,14 @@ public class Incident {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Instant getReported() {
return reported;
}