NativeQuery support
- initial working support - simple scalar queries
This commit is contained in:
parent
25fc3e2dce
commit
5dded5de7c
|
@ -6,9 +6,9 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.query.internal;
|
package org.hibernate.engine.query.internal;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
|
||||||
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
|
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.query.sql.internal.NativeSelectQueryPlanImpl;
|
||||||
import org.hibernate.query.sql.internal.ParameterParser;
|
import org.hibernate.query.sql.internal.ParameterParser;
|
||||||
import org.hibernate.query.sql.spi.NativeSelectQueryDefinition;
|
import org.hibernate.query.sql.spi.NativeSelectQueryDefinition;
|
||||||
import org.hibernate.query.sql.spi.NativeSelectQueryPlan;
|
import org.hibernate.query.sql.spi.NativeSelectQueryPlan;
|
||||||
|
@ -32,15 +32,12 @@ public class NativeQueryInterpreterStandardImpl implements NativeQueryInterprete
|
||||||
public <R> NativeSelectQueryPlan<R> createQueryPlan(
|
public <R> NativeSelectQueryPlan<R> createQueryPlan(
|
||||||
NativeSelectQueryDefinition<R> queryDefinition,
|
NativeSelectQueryDefinition<R> queryDefinition,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
return new NativeSelectQueryPlanImpl<>(
|
||||||
|
queryDefinition.getSqlString(),
|
||||||
// CustomQuery customQuery = new SQLCustomQuery(
|
queryDefinition.getAffectedTableNames(),
|
||||||
// specification.getQueryString(),
|
queryDefinition.getQueryParameterList(),
|
||||||
// specification.getQueryReturns(),
|
queryDefinition.getJdbcValuesMappingProducer(),
|
||||||
// specification.getQuerySpaces(),
|
queryDefinition.getRowTransformer()
|
||||||
// sessionFactory
|
);
|
||||||
// );
|
|
||||||
//
|
|
||||||
// return new NativeSQLQueryPlan( specification.getQueryString(), customQuery );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
@ -468,4 +469,15 @@ public final class ArrayHelper {
|
||||||
public static boolean isEmpty(Object[] array) {
|
public static boolean isEmpty(Object[] array) {
|
||||||
return array == null || array.length == 0;
|
return array == null || array.length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> void forEach(T[] array, Consumer<T> consumer) {
|
||||||
|
if ( array == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection ForLoopReplaceableByForEach
|
||||||
|
for ( int i = 0; i < array.length; i++ ) {
|
||||||
|
consumer.accept( array[ i ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,11 +49,12 @@ import org.hibernate.query.Query;
|
||||||
import org.hibernate.query.QueryParameter;
|
import org.hibernate.query.QueryParameter;
|
||||||
import org.hibernate.query.internal.QueryOptionsImpl;
|
import org.hibernate.query.internal.QueryOptionsImpl;
|
||||||
import org.hibernate.query.procedure.ProcedureParameter;
|
import org.hibernate.query.procedure.ProcedureParameter;
|
||||||
|
import org.hibernate.query.results.ResultSetMapping;
|
||||||
|
import org.hibernate.query.results.ResultSetMappingImpl;
|
||||||
import org.hibernate.query.spi.AbstractQuery;
|
import org.hibernate.query.spi.AbstractQuery;
|
||||||
import org.hibernate.query.spi.MutableQueryOptions;
|
import org.hibernate.query.spi.MutableQueryOptions;
|
||||||
import org.hibernate.query.spi.QueryParameterBindings;
|
import org.hibernate.query.spi.QueryParameterBindings;
|
||||||
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
||||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
|
||||||
import org.hibernate.result.NoMoreReturnsException;
|
import org.hibernate.result.NoMoreReturnsException;
|
||||||
import org.hibernate.result.Output;
|
import org.hibernate.result.Output;
|
||||||
import org.hibernate.result.ResultSetOutput;
|
import org.hibernate.result.ResultSetOutput;
|
||||||
|
@ -83,7 +84,7 @@ public class ProcedureCallImpl<R>
|
||||||
private final ProcedureParameterMetadataImpl parameterMetadata;
|
private final ProcedureParameterMetadataImpl parameterMetadata;
|
||||||
private final ProcedureParamBindings paramBindings;
|
private final ProcedureParamBindings paramBindings;
|
||||||
|
|
||||||
private final List<DomainResultProducer<?>> domainResultProducers;
|
private final ResultSetMapping resultSetMapping = new ResultSetMappingImpl();
|
||||||
|
|
||||||
private Set<String> synchronizedQuerySpaces;
|
private Set<String> synchronizedQuerySpaces;
|
||||||
|
|
||||||
|
@ -106,7 +107,6 @@ public class ProcedureCallImpl<R>
|
||||||
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
|
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
|
||||||
|
|
||||||
this.synchronizedQuerySpaces = null;
|
this.synchronizedQuerySpaces = null;
|
||||||
this.domainResultProducers = null;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* The result Class(es) return form
|
* The result Class(es) return form
|
||||||
|
@ -125,12 +125,11 @@ public class ProcedureCallImpl<R>
|
||||||
this.parameterMetadata = new ProcedureParameterMetadataImpl();
|
this.parameterMetadata = new ProcedureParameterMetadataImpl();
|
||||||
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
|
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
|
||||||
|
|
||||||
this.domainResultProducers = CollectionHelper.arrayList( resultClasses.length );
|
|
||||||
this.synchronizedQuerySpaces = new HashSet<>();
|
this.synchronizedQuerySpaces = new HashSet<>();
|
||||||
|
|
||||||
Util.resolveResultSetMappingClasses(
|
Util.resolveResultSetMappingClasses(
|
||||||
resultClasses,
|
resultClasses,
|
||||||
domainResultProducers::add,
|
resultSetMapping,
|
||||||
synchronizedQuerySpaces::add,
|
synchronizedQuerySpaces::add,
|
||||||
getSession().getFactory()
|
getSession().getFactory()
|
||||||
);
|
);
|
||||||
|
@ -156,12 +155,11 @@ public class ProcedureCallImpl<R>
|
||||||
this.parameterMetadata = new ProcedureParameterMetadataImpl();
|
this.parameterMetadata = new ProcedureParameterMetadataImpl();
|
||||||
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
|
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
|
||||||
|
|
||||||
this.domainResultProducers = CollectionHelper.arrayList( resultSetMappingNames.length );
|
|
||||||
this.synchronizedQuerySpaces = new HashSet<>();
|
this.synchronizedQuerySpaces = new HashSet<>();
|
||||||
|
|
||||||
Util.resolveResultSetMappingNames(
|
Util.resolveResultSetMappingNames(
|
||||||
resultSetMappingNames,
|
resultSetMappingNames,
|
||||||
domainResultProducers::add,
|
resultSetMapping,
|
||||||
synchronizedQuerySpaces::add,
|
synchronizedQuerySpaces::add,
|
||||||
getSession().getFactory()
|
getSession().getFactory()
|
||||||
);
|
);
|
||||||
|
@ -180,13 +178,12 @@ public class ProcedureCallImpl<R>
|
||||||
this.parameterMetadata = new ProcedureParameterMetadataImpl( memento, session );
|
this.parameterMetadata = new ProcedureParameterMetadataImpl( memento, session );
|
||||||
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
|
this.paramBindings = new ProcedureParamBindings( parameterMetadata, getSessionFactory() );
|
||||||
|
|
||||||
this.domainResultProducers = new ArrayList<>();
|
|
||||||
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
|
this.synchronizedQuerySpaces = CollectionHelper.makeCopy( memento.getQuerySpaces() );
|
||||||
|
|
||||||
Util.resolveResultSetMappings(
|
Util.resolveResultSetMappings(
|
||||||
memento.getResultSetMappingNames(),
|
memento.getResultSetMappingNames(),
|
||||||
memento.getResultSetMappingClasses(),
|
memento.getResultSetMappingClasses(),
|
||||||
domainResultProducers::add,
|
resultSetMapping,
|
||||||
synchronizedQuerySpaces::add,
|
synchronizedQuerySpaces::add,
|
||||||
getSession().getFactory()
|
getSession().getFactory()
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
import org.hibernate.query.named.NamedQueryRepository;
|
import org.hibernate.query.named.NamedQueryRepository;
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
import org.hibernate.query.spi.ResultSetMapping;
|
import org.hibernate.query.results.ResultSetMapping;
|
||||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
@ -32,7 +32,7 @@ public class Util {
|
||||||
public static void resolveResultSetMappings(
|
public static void resolveResultSetMappings(
|
||||||
String[] resultSetMappingNames,
|
String[] resultSetMappingNames,
|
||||||
Class[] resultSetMappingClasses,
|
Class[] resultSetMappingClasses,
|
||||||
Consumer<DomainResultProducer> resultProducerConsumer,
|
ResultSetMapping resultSetMapping,
|
||||||
Consumer<String> querySpaceConsumer,
|
Consumer<String> querySpaceConsumer,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
if ( ! ArrayHelper.isEmpty( resultSetMappingNames ) ) {
|
if ( ! ArrayHelper.isEmpty( resultSetMappingNames ) ) {
|
||||||
|
@ -40,10 +40,10 @@ public class Util {
|
||||||
if ( ! ArrayHelper.isEmpty( resultSetMappingClasses ) ) {
|
if ( ! ArrayHelper.isEmpty( resultSetMappingClasses ) ) {
|
||||||
throw new IllegalArgumentException( "Cannot specify both result-set mapping names and classes" );
|
throw new IllegalArgumentException( "Cannot specify both result-set mapping names and classes" );
|
||||||
}
|
}
|
||||||
resolveResultSetMappingNames( resultSetMappingNames, resultProducerConsumer, querySpaceConsumer, sessionFactory );
|
resolveResultSetMappingNames( resultSetMappingNames, resultSetMapping, querySpaceConsumer, sessionFactory );
|
||||||
}
|
}
|
||||||
else if ( ! ArrayHelper.isEmpty( resultSetMappingClasses ) ) {
|
else if ( ! ArrayHelper.isEmpty( resultSetMappingClasses ) ) {
|
||||||
resolveResultSetMappingClasses( resultSetMappingClasses, resultProducerConsumer, querySpaceConsumer, sessionFactory );
|
resolveResultSetMappingClasses( resultSetMappingClasses, resultSetMapping, querySpaceConsumer, sessionFactory );
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, nothing to resolve
|
// otherwise, nothing to resolve
|
||||||
|
@ -51,22 +51,24 @@ public class Util {
|
||||||
|
|
||||||
public static void resolveResultSetMappingNames(
|
public static void resolveResultSetMappingNames(
|
||||||
String[] resultSetMappingNames,
|
String[] resultSetMappingNames,
|
||||||
Consumer<DomainResultProducer> resultProducerConsumer,
|
ResultSetMapping resultSetMapping,
|
||||||
Consumer<String> querySpaceConsumer,
|
Consumer<String> querySpaceConsumer,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
final NamedQueryRepository namedQueryRepository = sessionFactory.getQueryEngine().getNamedQueryRepository();
|
final NamedQueryRepository namedQueryRepository = sessionFactory.getQueryEngine().getNamedQueryRepository();
|
||||||
|
|
||||||
for ( String resultSetMappingName : resultSetMappingNames ) {
|
for ( String resultSetMappingName : resultSetMappingNames ) {
|
||||||
final NamedResultSetMappingMemento memento = namedQueryRepository.getResultSetMappingMemento( resultSetMappingName );
|
final NamedResultSetMappingMemento memento = namedQueryRepository.getResultSetMappingMemento( resultSetMappingName );
|
||||||
final ResultSetMapping resultSetMapping = memento.toResultSetMapping();
|
memento.resolve(
|
||||||
resultProducerConsumer.accept( resultSetMapping );
|
resultSetMapping,
|
||||||
// todo (6.0) : determine query spaces - maybe passing the consumer to `NamedResultSetMappingMemento#toResultSetMapping`?
|
querySpaceConsumer,
|
||||||
|
sessionFactory
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void resolveResultSetMappingClasses(
|
public static void resolveResultSetMappingClasses(
|
||||||
Class[] resultSetMappingClasses,
|
Class[] resultSetMappingClasses,
|
||||||
Consumer<DomainResultProducer> resultProducerConsumer,
|
ResultSetMapping resultSetMapping,
|
||||||
Consumer<String> querySpaceConsumer,
|
Consumer<String> querySpaceConsumer,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
throw new NotYetImplementedFor6Exception( Util.class );
|
throw new NotYetImplementedFor6Exception( Util.class );
|
||||||
|
|
|
@ -25,7 +25,7 @@ public abstract class AbstractQueryParameter<T> implements QueryParameterImpleme
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disallowMultiValuedBinding() {
|
public void disallowMultiValuedBinding() {
|
||||||
QueryLogger.QUERY_LOGGER.debugf( "QueryParameter#disallowMultiValuedBinding() called : %s", this );
|
QueryLogger.QUERY_MESSAGE_LOGGER.debugf( "QueryParameter#disallowMultiValuedBinding() called : %s", this );
|
||||||
this.allowMultiValuedBinding = true;
|
this.allowMultiValuedBinding = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,8 @@ import static org.jboss.logging.Logger.Level.ERROR;
|
||||||
public interface QueryLogger extends BasicLogger {
|
public interface QueryLogger extends BasicLogger {
|
||||||
String LOGGER_NAME = "org.hibernate.orm.query";
|
String LOGGER_NAME = "org.hibernate.orm.query";
|
||||||
|
|
||||||
QueryLogger QUERY_LOGGER = Logger.getMessageLogger( QueryLogger.class, LOGGER_NAME );
|
Logger QUERY_LOGGER = Logger.getLogger( LOGGER_NAME );
|
||||||
|
QueryLogger QUERY_MESSAGE_LOGGER = Logger.getMessageLogger( QueryLogger.class, LOGGER_NAME );
|
||||||
|
|
||||||
boolean TRACE_ENABLED = QUERY_LOGGER.isTraceEnabled();
|
boolean TRACE_ENABLED = QUERY_LOGGER.isTraceEnabled();
|
||||||
boolean DEBUG_ENABLED = QUERY_LOGGER.isDebugEnabled();
|
boolean DEBUG_ENABLED = QUERY_LOGGER.isDebugEnabled();
|
||||||
|
|
|
@ -123,6 +123,10 @@ public class NamedQueryRepositoryImpl implements NamedQueryRepository {
|
||||||
resultSetMappingMementoMap.put( name, memento );
|
resultSetMappingMementoMap.put( name, memento );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Prepare repository for use
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare(
|
public void prepare(
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.internal;
|
package org.hibernate.query.internal;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
import org.hibernate.query.spi.ResultSetMapping;
|
import org.hibernate.query.results.ResultSetMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -27,7 +29,10 @@ public class NamedResultSetMappingMementoImpl implements NamedResultSetMappingMe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSetMapping toResultSetMapping() {
|
public void resolve(
|
||||||
|
ResultSetMapping resultSetMapping,
|
||||||
|
Consumer<String> querySpaceConsumer,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +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.query.internal;
|
|
||||||
|
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public interface NativeQueryReturnBuilder {
|
|
||||||
NativeSQLQueryReturn buildReturn();
|
|
||||||
}
|
|
|
@ -1,74 +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.query.internal;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryJoinReturn;
|
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
|
||||||
import org.hibernate.query.NativeQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class NativeQueryReturnBuilderFetchImpl implements NativeQuery.FetchReturn, NativeQueryReturnBuilder {
|
|
||||||
private final String alias;
|
|
||||||
private String ownerTableAlias;
|
|
||||||
private final String joinedPropertyName;
|
|
||||||
private LockMode lockMode = LockMode.READ;
|
|
||||||
private Map<String, String[]> propertyMappings;
|
|
||||||
|
|
||||||
public NativeQueryReturnBuilderFetchImpl(String alias, String ownerTableAlias, String joinedPropertyName) {
|
|
||||||
this.alias = alias;
|
|
||||||
this.ownerTableAlias = ownerTableAlias;
|
|
||||||
this.joinedPropertyName = joinedPropertyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQuery.FetchReturn setLockMode(LockMode lockMode) {
|
|
||||||
this.lockMode = lockMode;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQuery.FetchReturn addProperty(String propertyName, String columnAlias) {
|
|
||||||
addProperty( propertyName ).addColumnAlias( columnAlias );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQuery.ReturnProperty addProperty(final String propertyName) {
|
|
||||||
if ( propertyMappings == null ) {
|
|
||||||
propertyMappings = new HashMap<>();
|
|
||||||
}
|
|
||||||
return new NativeQuery.ReturnProperty() {
|
|
||||||
public NativeQuery.ReturnProperty addColumnAlias(String columnAlias) {
|
|
||||||
String[] columnAliases = propertyMappings.get( propertyName );
|
|
||||||
if ( columnAliases == null ) {
|
|
||||||
columnAliases = new String[] {columnAlias};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String[] newColumnAliases = new String[columnAliases.length + 1];
|
|
||||||
System.arraycopy( columnAliases, 0, newColumnAliases, 0, columnAliases.length );
|
|
||||||
newColumnAliases[columnAliases.length] = columnAlias;
|
|
||||||
columnAliases = newColumnAliases;
|
|
||||||
}
|
|
||||||
propertyMappings.put( propertyName, columnAliases );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeSQLQueryReturn buildReturn() {
|
|
||||||
return new NativeSQLQueryJoinReturn(
|
|
||||||
alias,
|
|
||||||
ownerTableAlias,
|
|
||||||
joinedPropertyName,
|
|
||||||
propertyMappings,
|
|
||||||
lockMode
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +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.query.internal;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
|
||||||
import org.hibernate.query.NativeQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class NativeQueryReturnBuilderRootImpl implements NativeQuery.RootReturn, NativeQueryReturnBuilder {
|
|
||||||
private final String alias;
|
|
||||||
private final String entityName;
|
|
||||||
private LockMode lockMode = LockMode.READ;
|
|
||||||
private Map<String, String[]> propertyMappings;
|
|
||||||
|
|
||||||
public NativeQueryReturnBuilderRootImpl(String alias, String entityName) {
|
|
||||||
this.alias = alias;
|
|
||||||
this.entityName = entityName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQuery.RootReturn setLockMode(LockMode lockMode) {
|
|
||||||
this.lockMode = lockMode;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQuery.RootReturn setDiscriminatorAlias(String alias) {
|
|
||||||
addProperty( "class", alias );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQuery.RootReturn addProperty(String propertyName, String columnAlias) {
|
|
||||||
addProperty( propertyName ).addColumnAlias( columnAlias );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeQuery.ReturnProperty addProperty(final String propertyName) {
|
|
||||||
if ( propertyMappings == null ) {
|
|
||||||
propertyMappings = new HashMap<>();
|
|
||||||
}
|
|
||||||
return new NativeQuery.ReturnProperty() {
|
|
||||||
public NativeQuery.ReturnProperty addColumnAlias(String columnAlias) {
|
|
||||||
String[] columnAliases = propertyMappings.get( propertyName );
|
|
||||||
if ( columnAliases == null ) {
|
|
||||||
columnAliases = new String[] {columnAlias};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String[] newColumnAliases = new String[columnAliases.length + 1];
|
|
||||||
System.arraycopy( columnAliases, 0, newColumnAliases, 0, columnAliases.length );
|
|
||||||
newColumnAliases[columnAliases.length] = columnAlias;
|
|
||||||
columnAliases = newColumnAliases;
|
|
||||||
}
|
|
||||||
propertyMappings.put( propertyName, columnAliases );
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public NativeSQLQueryReturn buildReturn() {
|
|
||||||
return new NativeSQLQueryRootReturn( alias, entityName, propertyMappings, lockMode );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,8 +6,11 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.named;
|
package org.hibernate.query.named;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.query.spi.ResultSetMapping;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.query.results.ResultSetMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to keep information about named result mappings defined by the
|
* Used to keep information about named result mappings defined by the
|
||||||
|
@ -27,8 +30,5 @@ import org.hibernate.query.spi.ResultSetMapping;
|
||||||
public interface NamedResultSetMappingMemento {
|
public interface NamedResultSetMappingMemento {
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
/**
|
void resolve(ResultSetMapping resultSetMapping, Consumer<String> querySpaceConsumer, SessionFactoryImplementor sessionFactory);
|
||||||
* todo (6.0) : determine the proper arguments. depends on how we port JdbcValues, etc from the original 6.0 work
|
|
||||||
*/
|
|
||||||
ResultSetMapping toResultSetMapping();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public abstract class AbstractPropertyContainer<T extends AbstractPropertyContainer<T>> implements PropertyContainer {
|
||||||
|
private Map<String,FetchBuilder> fetchBuilderMap;
|
||||||
|
|
||||||
|
protected abstract String getPropertyBase();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T addProperty(String propertyName, String columnAlias) {
|
||||||
|
final FetchBuilder fetchBuilder = addProperty( propertyName );
|
||||||
|
fetchBuilder.addColumnAlias( columnAlias );
|
||||||
|
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T addProperty(String propertyName, String... columnAliases) {
|
||||||
|
final FetchBuilder fetchBuilder = addProperty( propertyName );
|
||||||
|
ArrayHelper.forEach( columnAliases, fetchBuilder::addColumnAlias );
|
||||||
|
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchBuilder addProperty(String propertyName) {
|
||||||
|
if ( fetchBuilderMap == null ) {
|
||||||
|
fetchBuilderMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final FetchBuilder existing = fetchBuilderMap.get( propertyName );
|
||||||
|
if ( existing != null ) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
|
"Fetch was already defined for %s.%s : %s",
|
||||||
|
getPropertyBase(),
|
||||||
|
propertyName,
|
||||||
|
existing
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final FetchBuilder fetchBuilder = new StandardFetchBuilderImpl();
|
||||||
|
fetchBuilderMap.put( propertyName, fetchBuilder );
|
||||||
|
|
||||||
|
return fetchBuilder;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface BuilderGraphNode {
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class Builders {
|
||||||
|
public static ScalarResultBuilder scalar(
|
||||||
|
String columnAlias,
|
||||||
|
BasicType<?> type) {
|
||||||
|
return new ScalarResultBuilder( columnAlias, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScalarResultBuilder scalar(
|
||||||
|
String columnAlias,
|
||||||
|
Class<?> javaType,
|
||||||
|
SessionFactoryImplementor factory) {
|
||||||
|
return new ScalarResultBuilder(
|
||||||
|
columnAlias,
|
||||||
|
factory.getTypeConfiguration().getBasicTypeForJavaType( javaType )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DomainResult<?> implicitScalarDomainResult(
|
||||||
|
int colIndex,
|
||||||
|
String columnName,
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||||
|
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( colIndex );
|
||||||
|
final BasicJavaDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||||
|
final BasicType<?> jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
|
||||||
|
sqlSelectionConsumer.accept( new SqlSelectionImpl( colIndex, jdbcMapping ) );
|
||||||
|
return new BasicResult<>( colIndex, columnName, javaTypeDescriptor );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EntityResultBuilder entity(String tableAlias, String entityName) {
|
||||||
|
throw new NotYetImplementedFor6Exception( );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LegacyFetchBuilder fetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
|
||||||
|
throw new NotYetImplementedFor6Exception( );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.query.NativeQuery;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class EntityResultBuilder
|
||||||
|
extends AbstractPropertyContainer<EntityResultBuilder>
|
||||||
|
implements ResultBuilder, NativeQuery.RootReturn {
|
||||||
|
private final String entityName;
|
||||||
|
private final String tableAlias;
|
||||||
|
|
||||||
|
private LockMode lockMode;
|
||||||
|
|
||||||
|
private String discriminatorColumnAlias;
|
||||||
|
|
||||||
|
public EntityResultBuilder(String entityName, String tableAlias) {
|
||||||
|
this.entityName = entityName;
|
||||||
|
this.tableAlias = tableAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPropertyBase() {
|
||||||
|
return entityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResult<?> buildReturn(
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||||
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityResultBuilder setLockMode(LockMode lockMode) {
|
||||||
|
this.lockMode = lockMode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityResultBuilder setDiscriminatorAlias(String columnAlias) {
|
||||||
|
this.discriminatorColumnAlias = columnAlias;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.query.NativeQuery;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for building a single {@link DomainResult} instance as part of
|
||||||
|
* the overall mapping of native / procedure query results.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
public interface FetchBuilder extends NativeQuery.ReturnProperty {
|
||||||
|
Fetch buildFetch(
|
||||||
|
FetchParent parent,
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
|
SessionFactoryImplementor sessionFactory);
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of JdbcValuesMapping for native / procedure queries
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JdbcValuesMappingImpl implements JdbcValuesMapping {
|
||||||
|
private final List<SqlSelection> sqlSelections;
|
||||||
|
private final List<DomainResult<?>> domainResults;
|
||||||
|
|
||||||
|
public JdbcValuesMappingImpl(
|
||||||
|
List<SqlSelection> sqlSelections,
|
||||||
|
List<DomainResult<?>> domainResults) {
|
||||||
|
this.sqlSelections = sqlSelections;
|
||||||
|
this.domainResults = domainResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SqlSelection> getSqlSelections() {
|
||||||
|
return sqlSelections;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
public List<DomainResult> getDomainResults() {
|
||||||
|
return (List) domainResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
public List<DomainResultAssembler> resolveAssemblers(AssemblerCreationState creationState) {
|
||||||
|
final List<DomainResultAssembler> assemblers = new ArrayList<>( domainResults.size() );
|
||||||
|
domainResults.forEach(
|
||||||
|
domainResult -> assemblers.add( domainResult.createResultAssembler( creationState ) )
|
||||||
|
);
|
||||||
|
return assemblers;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import org.hibernate.query.NativeQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface LegacyFetchBuilder extends FetchBuilder, NativeQuery.FetchReturn {
|
||||||
|
String getOwnerAlias();
|
||||||
|
String getFetchAlias();
|
||||||
|
String getFetchedAttributeName();
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface PropertyContainer {
|
||||||
|
/**
|
||||||
|
* Add a simple property-to-one-column mapping.
|
||||||
|
*/
|
||||||
|
PropertyContainer addProperty(String propertyName, String columnAlias);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a property mapped to multiple columns
|
||||||
|
*/
|
||||||
|
PropertyContainer addProperty(String propertyName, String... columnAliases);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a property whose columns can later be defined using {@link FetchBuilder#addColumnAlias}
|
||||||
|
*/
|
||||||
|
FetchBuilder addProperty(String propertyName);
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for building a single {@link DomainResult} instance as part of
|
||||||
|
* the overall mapping of native / procedure query results.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
public interface ResultBuilder {
|
||||||
|
DomainResult<?> buildReturn(
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
BiFunction<String,String,LegacyFetchBuilder> legacyFetchResolver,
|
||||||
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
|
SessionFactoryImplementor sessionFactory);
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acts as the {@link JdbcValuesMappingProducer} for {@link org.hibernate.query.NativeQuery}
|
||||||
|
* or {@link org.hibernate.procedure.ProcedureCall} / {@link javax.persistence.StoredProcedureQuery}
|
||||||
|
* instances.
|
||||||
|
*
|
||||||
|
* Collects builders for results and fetches and manages resolving them via JdbcValuesMappingProducer
|
||||||
|
*
|
||||||
|
* @see org.hibernate.query.NativeQuery#addScalar
|
||||||
|
* @see org.hibernate.query.NativeQuery#addEntity
|
||||||
|
* @see org.hibernate.query.NativeQuery#addJoin
|
||||||
|
* @see org.hibernate.query.NativeQuery#addFetch
|
||||||
|
* @see org.hibernate.query.NativeQuery#addRoot
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
public interface ResultSetMapping extends JdbcValuesMappingProducer {
|
||||||
|
int getNumberOfResultBuilders();
|
||||||
|
|
||||||
|
void visitResultBuilders(BiConsumer<Integer, ResultBuilder> resultBuilderConsumer);
|
||||||
|
|
||||||
|
void addResultBuilder(ResultBuilder resultBuilder);
|
||||||
|
void addLegacyFetchBuilder(LegacyFetchBuilder fetchBuilder);
|
||||||
|
|
||||||
|
NamedResultSetMappingMemento toMemento(String name);
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
|
import org.hibernate.Internal;
|
||||||
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Incubating
|
||||||
|
@Internal
|
||||||
|
public class ResultSetMappingImpl implements ResultSetMapping {
|
||||||
|
private List<ResultBuilder> resultBuilders;
|
||||||
|
private Map<String, Map<String,LegacyFetchBuilder>> legacyFetchBuilders;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfResultBuilders() {
|
||||||
|
return resultBuilders == null ? 0 : resultBuilders.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitResultBuilders(BiConsumer<Integer, ResultBuilder> resultBuilderConsumer) {
|
||||||
|
if ( resultBuilders == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < resultBuilders.size(); i++ ) {
|
||||||
|
resultBuilderConsumer.accept( i, resultBuilders.get( i ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResultBuilder(ResultBuilder resultBuilder) {
|
||||||
|
if ( resultBuilders == null ) {
|
||||||
|
resultBuilders = new ArrayList<>();
|
||||||
|
}
|
||||||
|
resultBuilders.add( resultBuilder );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addLegacyFetchBuilder(LegacyFetchBuilder fetchBuilder) {
|
||||||
|
final Map<String, LegacyFetchBuilder> existingFetchBuildersByOwner;
|
||||||
|
|
||||||
|
if ( legacyFetchBuilders == null ) {
|
||||||
|
legacyFetchBuilders = new HashMap<>();
|
||||||
|
existingFetchBuildersByOwner = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
existingFetchBuildersByOwner = legacyFetchBuilders.get( fetchBuilder.getOwnerAlias() );
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, LegacyFetchBuilder> fetchBuildersByOwner;
|
||||||
|
if ( existingFetchBuildersByOwner == null ) {
|
||||||
|
fetchBuildersByOwner = new HashMap<>();
|
||||||
|
legacyFetchBuilders.put( fetchBuilder.getOwnerAlias(), fetchBuildersByOwner );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fetchBuildersByOwner = existingFetchBuildersByOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
final LegacyFetchBuilder previousBuilder = fetchBuildersByOwner.put( fetchBuilder.getFetchedAttributeName(), fetchBuilder );
|
||||||
|
if ( previousBuilder != null ) {
|
||||||
|
// todo (6.0) : error? log? nothing?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcValuesMapping resolve(
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
final List<SqlSelection> sqlSelections = new ArrayList<>( jdbcResultsMetadata.getColumnCount() );
|
||||||
|
|
||||||
|
final int numberOfResults;
|
||||||
|
|
||||||
|
if ( resultBuilders == null ) {
|
||||||
|
numberOfResults = jdbcResultsMetadata.getColumnCount();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
numberOfResults = resultBuilders.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<DomainResult<?>> domainResults = new ArrayList<>( numberOfResults );
|
||||||
|
|
||||||
|
for ( int i = 0; i < numberOfResults; i++ ) {
|
||||||
|
final ResultBuilder resultBuilder = resultBuilders != null
|
||||||
|
? resultBuilders.get( i )
|
||||||
|
: null;
|
||||||
|
|
||||||
|
final DomainResult<?> domainResult;
|
||||||
|
if ( resultBuilder == null ) {
|
||||||
|
domainResult = makeImplicitDomainResult(
|
||||||
|
i,
|
||||||
|
sqlSelections::add,
|
||||||
|
jdbcResultsMetadata,
|
||||||
|
sessionFactory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
domainResult = resultBuilder.buildReturn(
|
||||||
|
jdbcResultsMetadata,
|
||||||
|
(ownerAlias, fetchName) -> {
|
||||||
|
if ( legacyFetchBuilders == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, LegacyFetchBuilder> fetchBuildersForOwner = legacyFetchBuilders.get(
|
||||||
|
ownerAlias );
|
||||||
|
if ( fetchBuildersForOwner == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetchBuildersForOwner.get( fetchName );
|
||||||
|
},
|
||||||
|
sqlSelections::add,
|
||||||
|
sessionFactory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
domainResults.add( domainResult );
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JdbcValuesMappingImpl( sqlSelections, domainResults );
|
||||||
|
}
|
||||||
|
|
||||||
|
private DomainResult<?> makeImplicitDomainResult(
|
||||||
|
int valuesArrayPosition,
|
||||||
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
final int jdbcPosition = valuesArrayPosition + 1;
|
||||||
|
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||||
|
|
||||||
|
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||||
|
|
||||||
|
final JavaTypeDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||||
|
|
||||||
|
final BasicType<?> jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve(
|
||||||
|
javaTypeDescriptor,
|
||||||
|
sqlTypeDescriptor
|
||||||
|
);
|
||||||
|
|
||||||
|
final String name = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
|
||||||
|
|
||||||
|
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
|
||||||
|
sqlSelectionConsumer.accept( sqlSelection );
|
||||||
|
|
||||||
|
return new BasicResult( valuesArrayPosition, name, jdbcMapping.getJavaTypeDescriptor() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NamedResultSetMappingMemento toMemento(String name) {
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.query.results;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.persistence.ColumnResult
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ScalarResultBuilder implements ResultBuilder {
|
||||||
|
private final String explicitName;
|
||||||
|
private final BasicType<?> explicitType;
|
||||||
|
|
||||||
|
ScalarResultBuilder(String explicitName, BasicType<?> explicitType) {
|
||||||
|
assert explicitName != null;
|
||||||
|
this.explicitName = explicitName;
|
||||||
|
this.explicitType = explicitType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExplicitName() {
|
||||||
|
return explicitName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainResult<?> buildReturn(
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
BiFunction<String, String, LegacyFetchBuilder> legacyFetchResolver,
|
||||||
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( explicitName );
|
||||||
|
final int valuesArrayPosition = jdbcPosition - 1;
|
||||||
|
|
||||||
|
final BasicType<?> jdbcMapping;
|
||||||
|
|
||||||
|
if ( explicitType != null ) {
|
||||||
|
jdbcMapping = explicitType;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
|
||||||
|
|
||||||
|
final SqlTypeDescriptor sqlTypeDescriptor = jdbcResultsMetadata.resolveSqlTypeDescriptor( jdbcPosition );
|
||||||
|
final JavaTypeDescriptor<?> javaTypeDescriptor = sqlTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||||
|
|
||||||
|
jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, sqlTypeDescriptor );
|
||||||
|
}
|
||||||
|
|
||||||
|
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
|
||||||
|
sqlSelectionConsumer.accept( sqlSelection );
|
||||||
|
|
||||||
|
return new BasicResult( valuesArrayPosition, explicitName, jdbcMapping.getJavaTypeDescriptor() );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||||
|
import org.hibernate.sql.ast.SqlAstWalker;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SqlSelection for NativeQuery
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SqlSelectionImpl implements SqlSelection {
|
||||||
|
private final int valuesArrayPosition;
|
||||||
|
private final BasicValuedMapping valueMapping;
|
||||||
|
|
||||||
|
public SqlSelectionImpl(int valuesArrayPosition, BasicValuedMapping valueMapping) {
|
||||||
|
this.valuesArrayPosition = valuesArrayPosition;
|
||||||
|
this.valueMapping = valueMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueExtractor getJdbcValueExtractor() {
|
||||||
|
return valueMapping.getJdbcMapping().getJdbcValueExtractor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getValuesArrayPosition() {
|
||||||
|
return valuesArrayPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MappingModelExpressable getExpressionType() {
|
||||||
|
return valueMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(SqlAstWalker sqlAstWalker) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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.results;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.query.NativeQuery;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||||
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class StandardFetchBuilderImpl implements FetchBuilder {
|
||||||
|
@Override
|
||||||
|
public Fetch buildFetch(
|
||||||
|
FetchParent parent,
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NativeQuery.ReturnProperty addColumnAlias(String columnAlias) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for defining result-set mappings used in {@link org.hibernate.query.NativeQuery}
|
||||||
|
* and {@link org.hibernate.procedure.ProcedureCall} / {@link javax.persistence.StoredProcedureQuery}.
|
||||||
|
* These result-set mappings are used to map the values in the JDBC {@link java.sql.ResultSet}
|
||||||
|
* into "domain results" (see {@link org.hibernate.sql.results.graph.DomainResult}).
|
||||||
|
*
|
||||||
|
* @see org.hibernate.query.results.ResultSetMapping
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
package org.hibernate.query.results;
|
|
@ -304,7 +304,7 @@ public class QueryEngine {
|
||||||
StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " );
|
StringBuilder failingQueries = new StringBuilder( "Errors in named queries: " );
|
||||||
String sep = "";
|
String sep = "";
|
||||||
for ( Map.Entry<String, HibernateException> entry : errors.entrySet() ) {
|
for ( Map.Entry<String, HibernateException> entry : errors.entrySet() ) {
|
||||||
QueryLogger.QUERY_LOGGER.namedQueryError( entry.getKey(), entry.getValue() );
|
QueryLogger.QUERY_MESSAGE_LOGGER.namedQueryError( entry.getKey(), entry.getValue() );
|
||||||
failingQueries.append( sep ).append( entry.getKey() );
|
failingQueries.append( sep ).append( entry.getKey() );
|
||||||
sep = ", ";
|
sep = ", ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +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.query.spi;
|
|
||||||
|
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
|
||||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder for {@link DomainResult} instances related to native SQL query results.
|
|
||||||
*
|
|
||||||
* todo (6.0) : Perhaps this should be a builder for QueryResultProducer instances instead?
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public interface QueryResultBuilder {
|
|
||||||
// todo (6.0) : need to add the notion of "builders" that nest inside other builders.
|
|
||||||
// Nesting can happen as:
|
|
||||||
//
|
|
||||||
// For a scalar, it might represent:
|
|
||||||
// 1) a top-level QueryResult
|
|
||||||
// 2) a column within the attribute mapping for entity (or composite?)
|
|
||||||
// 3) an argument to a dynamic-instantiation
|
|
||||||
//
|
|
||||||
// For an attribute, it always represents a non-QueryResult. At least I
|
|
||||||
// think that is accurate - validate this, can an attribute be defined
|
|
||||||
// as a top-level QueryResult? dynamic-instantiation argument? - JPA at least does not support that
|
|
||||||
//
|
|
||||||
// For dynamic-instantiation, it might represent:
|
|
||||||
// 1) a top-level QueryResult
|
|
||||||
// 2) dynamic-instantiation argument (non-JPA)
|
|
||||||
|
|
||||||
JavaTypeDescriptor getResultType();
|
|
||||||
|
|
||||||
DomainResult buildReturn(DomainResultCreationState creationState);
|
|
||||||
}
|
|
|
@ -1,31 +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.query.spi;
|
|
||||||
|
|
||||||
import org.hibernate.Incubating;
|
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
|
||||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Describes a ResultSet mapping applied to either a {@link org.hibernate.query.NativeQuery}
|
|
||||||
* or a {@link org.hibernate.procedure.ProcedureCall} / {@link javax.persistence.StoredProcedureQuery}.
|
|
||||||
*
|
|
||||||
* It is either generated from a {@link NamedResultSetMappingMemento} or
|
|
||||||
* on-the-fly via Hibernate's {@link org.hibernate.query.NativeQuery} contract. Acts
|
|
||||||
* as the {@link DomainResultProducer} for these uses
|
|
||||||
*
|
|
||||||
* @see org.hibernate.query.NativeQuery#addScalar
|
|
||||||
* @see org.hibernate.query.NativeQuery#addEntity
|
|
||||||
* @see org.hibernate.query.NativeQuery#addJoin
|
|
||||||
* @see org.hibernate.query.NativeQuery#addFetch
|
|
||||||
* @see org.hibernate.query.NativeQuery#addRoot
|
|
||||||
*
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
@Incubating
|
|
||||||
public interface ResultSetMapping extends DomainResultProducer {
|
|
||||||
}
|
|
|
@ -11,7 +11,6 @@ import java.time.Instant;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -38,9 +37,6 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.ScrollMode;
|
import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
|
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryConstructorReturn;
|
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
|
||||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.graph.GraphSemantic;
|
import org.hibernate.graph.GraphSemantic;
|
||||||
|
@ -56,12 +52,13 @@ import org.hibernate.query.Query;
|
||||||
import org.hibernate.query.QueryParameter;
|
import org.hibernate.query.QueryParameter;
|
||||||
import org.hibernate.query.ResultListTransformer;
|
import org.hibernate.query.ResultListTransformer;
|
||||||
import org.hibernate.query.TupleTransformer;
|
import org.hibernate.query.TupleTransformer;
|
||||||
import org.hibernate.query.internal.NativeQueryReturnBuilder;
|
|
||||||
import org.hibernate.query.internal.NativeQueryReturnBuilderFetchImpl;
|
|
||||||
import org.hibernate.query.internal.NativeQueryReturnBuilderRootImpl;
|
|
||||||
import org.hibernate.query.internal.ParameterMetadataImpl;
|
import org.hibernate.query.internal.ParameterMetadataImpl;
|
||||||
import org.hibernate.query.internal.QueryOptionsImpl;
|
import org.hibernate.query.internal.QueryOptionsImpl;
|
||||||
import org.hibernate.query.internal.QueryParameterBindingsImpl;
|
import org.hibernate.query.internal.QueryParameterBindingsImpl;
|
||||||
|
import org.hibernate.query.results.Builders;
|
||||||
|
import org.hibernate.query.results.EntityResultBuilder;
|
||||||
|
import org.hibernate.query.results.LegacyFetchBuilder;
|
||||||
|
import org.hibernate.query.results.ResultSetMappingImpl;
|
||||||
import org.hibernate.query.spi.AbstractQuery;
|
import org.hibernate.query.spi.AbstractQuery;
|
||||||
import org.hibernate.query.spi.MutableQueryOptions;
|
import org.hibernate.query.spi.MutableQueryOptions;
|
||||||
import org.hibernate.query.spi.NonSelectQueryPlan;
|
import org.hibernate.query.spi.NonSelectQueryPlan;
|
||||||
|
@ -84,6 +81,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||||
import org.hibernate.sql.results.spi.RowTransformer;
|
import org.hibernate.sql.results.spi.RowTransformer;
|
||||||
import org.hibernate.transform.ResultTransformer;
|
import org.hibernate.transform.ResultTransformer;
|
||||||
|
import org.hibernate.type.BasicType;
|
||||||
|
|
||||||
import static org.hibernate.jpa.QueryHints.HINT_NATIVE_LOCKMODE;
|
import static org.hibernate.jpa.QueryHints.HINT_NATIVE_LOCKMODE;
|
||||||
|
|
||||||
|
@ -104,11 +102,7 @@ public class NativeQueryImpl<R>
|
||||||
|
|
||||||
private Set<String> querySpaces;
|
private Set<String> querySpaces;
|
||||||
|
|
||||||
|
private ResultSetMappingImpl resultSetMapping = new ResultSetMappingImpl();
|
||||||
|
|
||||||
private List<NativeSQLQueryReturn> queryReturns;
|
|
||||||
private List<NativeQueryReturnBuilder> queryReturnBuilders;
|
|
||||||
private boolean autoDiscoverTypes;
|
|
||||||
|
|
||||||
private Object collectionKey;
|
private Object collectionKey;
|
||||||
private NativeQueryInterpreter nativeQueryInterpreter;
|
private NativeQueryInterpreter nativeQueryInterpreter;
|
||||||
|
@ -141,7 +135,10 @@ public class NativeQueryImpl<R>
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
this( memento, session );
|
this( memento, session );
|
||||||
|
|
||||||
// todo (6.0) : validate `resultJavaType` against specified result-set mapping
|
// todo (6.0) : need to add handling for `javax.persistence.NamedNativeQuery#resultSetMapping`
|
||||||
|
// and `javax.persistence.NamedNativeQuery#resultClass`
|
||||||
|
|
||||||
|
// todo (6.0) : relatedly, does `resultJavaType` come from `NamedNativeQuery#resultClass`?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -152,6 +149,11 @@ public class NativeQueryImpl<R>
|
||||||
String resultSetMappingName,
|
String resultSetMappingName,
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
this( memento, session );
|
this( memento, session );
|
||||||
|
|
||||||
|
// todo (6.0) : need to add handling for `javax.persistence.NamedNativeQuery#resultSetMapping`
|
||||||
|
// and `javax.persistence.NamedNativeQuery#resultClass`
|
||||||
|
|
||||||
|
// todo (6.0) : relatedly, does `resultSetMappingName` come from `NamedNativeQuery#resultSetMapping`?
|
||||||
}
|
}
|
||||||
|
|
||||||
private ParameterInterpretation resolveParameterInterpretation(SharedSessionContractImplementor session) {
|
private ParameterInterpretation resolveParameterInterpretation(SharedSessionContractImplementor session) {
|
||||||
|
@ -199,7 +201,6 @@ public class NativeQueryImpl<R>
|
||||||
|
|
||||||
this.sqlString = sqlString;
|
this.sqlString = sqlString;
|
||||||
|
|
||||||
this.queryReturns = new ArrayList<>();
|
|
||||||
this.querySpaces = new HashSet<>();
|
this.querySpaces = new HashSet<>();
|
||||||
|
|
||||||
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
|
final ParameterInterpretation parameterInterpretation = resolveParameterInterpretation( session );
|
||||||
|
@ -332,44 +333,56 @@ public class NativeQueryImpl<R>
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private SelectQueryPlan<R> resolveSelectQueryPlan() {
|
private SelectQueryPlan<R> resolveSelectQueryPlan() {
|
||||||
|
|
||||||
SelectQueryPlan<R> queryPlan = null;
|
|
||||||
|
|
||||||
|
|
||||||
final JdbcValuesMappingProducer resultSetMapping = getJdbcValuesMappingProducer();
|
|
||||||
|
|
||||||
final QueryInterpretationCache.Key cacheKey = generateSelectInterpretationsKey( resultSetMapping );
|
final QueryInterpretationCache.Key cacheKey = generateSelectInterpretationsKey( resultSetMapping );
|
||||||
if ( cacheKey != null ) {
|
if ( cacheKey != null ) {
|
||||||
return getSession().getFactory().getQueryEngine().getInterpretationCache().resolveSelectQueryPlan(
|
return getSession().getFactory().getQueryEngine().getInterpretationCache().resolveSelectQueryPlan(
|
||||||
cacheKey,
|
cacheKey,
|
||||||
this::createQueryPlan
|
() -> createQueryPlan( resultSetMapping )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return createQueryPlan();
|
return createQueryPlan( resultSetMapping );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private NativeSelectQueryPlan<R> createQueryPlan() {
|
private NativeSelectQueryPlan<R> createQueryPlan(JdbcValuesMappingProducer jdbcValuesMappingProducer) {
|
||||||
final RowTransformer rowTransformer = resolveRowTransformer();
|
final RowTransformer<?> rowTransformer = null;
|
||||||
|
|
||||||
return getSessionFactory().getQueryEngine().getNativeQueryInterpreter().createQueryPlan(
|
final NativeSelectQueryDefinition queryDefinition = new NativeSelectQueryDefinition() {
|
||||||
generateSelectQueryDefinition(),
|
@Override
|
||||||
getSessionFactory()
|
public String getSqlString() {
|
||||||
);
|
return NativeQueryImpl.this.getQueryString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private JdbcValuesMappingProducer getJdbcValuesMappingProducer() {
|
@Override
|
||||||
// todo (6.0) - need to resolve SqlSelections as well as resolving ResultBuilders and FetchBuilders into QueryResult trees
|
public boolean isCallable() {
|
||||||
// also need to account for the edge case where the user passed just the
|
return false;
|
||||||
// query string and no mappings (see ResultSetMappingUndefinedImpl)
|
|
||||||
throw new NotYetImplementedFor6Exception( );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private RowTransformer resolveRowTransformer() {
|
@Override
|
||||||
// todo (6.0) - need to resolve the RowTransformer to use, if one.
|
public List<QueryParameterImplementor<?>> getQueryParameterList() {
|
||||||
// todo (6.0) - what about ResultListTransformer?
|
return NativeQueryImpl.this.occurrenceOrderedParamList;
|
||||||
throw new NotYetImplementedFor6Exception( );
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcValuesMappingProducer getJdbcValuesMappingProducer() {
|
||||||
|
return jdbcValuesMappingProducer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RowTransformer getRowTransformer() {
|
||||||
|
return rowTransformer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getAffectedTableNames() {
|
||||||
|
return querySpaces;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return getSessionFactory().getQueryEngine()
|
||||||
|
.getNativeQueryInterpreter()
|
||||||
|
.createQueryPlan( queryDefinition, getSessionFactory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private SelectInterpretationsKey generateSelectInterpretationsKey(JdbcValuesMappingProducer resultSetMapping) {
|
private SelectInterpretationsKey generateSelectInterpretationsKey(JdbcValuesMappingProducer resultSetMapping) {
|
||||||
|
@ -398,57 +411,6 @@ public class NativeQueryImpl<R>
|
||||||
return limit.getFirstRow() != null || limit.getMaxRows() != null;
|
return limit.getFirstRow() != null || limit.getMaxRows() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NativeSelectQueryDefinition<R> generateSelectQueryDefinition() {
|
|
||||||
return new NativeSelectQueryDefinition() {
|
|
||||||
@Override
|
|
||||||
public String getSqlString() {
|
|
||||||
return NativeQueryImpl.this.getQueryString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCallable() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<QueryParameterImplementor<?>> getQueryParameterList() {
|
|
||||||
return NativeQueryImpl.this.occurrenceOrderedParamList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JdbcValuesMappingProducer getJdbcValuesMappingProducer() {
|
|
||||||
return NativeQueryImpl.this.getJdbcValuesMappingProducer();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RowTransformer getRowTransformer() {
|
|
||||||
return NativeQueryImpl.this.resolveRowTransformer();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getAffectedTableNames() {
|
|
||||||
return querySpaces;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareQueryReturnsIfNecessary() {
|
|
||||||
if ( queryReturnBuilders != null ) {
|
|
||||||
if ( !queryReturnBuilders.isEmpty() ) {
|
|
||||||
if ( queryReturns != null ) {
|
|
||||||
queryReturns.clear();
|
|
||||||
queryReturns = null;
|
|
||||||
}
|
|
||||||
queryReturns = new ArrayList<>();
|
|
||||||
for ( NativeQueryReturnBuilder builder : queryReturnBuilders ) {
|
|
||||||
queryReturns.add( builder.buildReturn() );
|
|
||||||
}
|
|
||||||
queryReturnBuilders.clear();
|
|
||||||
}
|
|
||||||
queryReturnBuilders = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
|
protected ScrollableResultsImplementor doScroll(ScrollMode scrollMode) {
|
||||||
return resolveSelectQueryPlan().performScroll( scrollMode, this );
|
return resolveSelectQueryPlan().performScroll( scrollMode, this );
|
||||||
|
@ -456,27 +418,6 @@ public class NativeQueryImpl<R>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void beforeQuery(boolean txnRequired) {
|
protected void beforeQuery(boolean txnRequired) {
|
||||||
prepareQueryReturnsIfNecessary();
|
|
||||||
boolean noReturns = queryReturns == null || queryReturns.isEmpty();
|
|
||||||
if ( noReturns ) {
|
|
||||||
this.autoDiscoverTypes = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for ( NativeSQLQueryReturn queryReturn : queryReturns ) {
|
|
||||||
if ( queryReturn instanceof NativeSQLQueryScalarReturn ) {
|
|
||||||
NativeSQLQueryScalarReturn scalar = (NativeSQLQueryScalarReturn) queryReturn;
|
|
||||||
if ( scalar.getType() == null ) {
|
|
||||||
autoDiscoverTypes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( NativeSQLQueryConstructorReturn.class.isInstance( queryReturn ) ) {
|
|
||||||
autoDiscoverTypes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
super.beforeQuery( txnRequired );
|
super.beforeQuery( txnRequired );
|
||||||
|
|
||||||
if ( getSynchronizedQuerySpaces() != null && !getSynchronizedQuerySpaces().isEmpty() ) {
|
if ( getSynchronizedQuerySpaces() != null && !getSynchronizedQuerySpaces().isEmpty() ) {
|
||||||
|
@ -537,36 +478,24 @@ public class NativeQueryImpl<R>
|
||||||
return addScalar( columnAlias, null );
|
return addScalar( columnAlias, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType type) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType type) {
|
public NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType type) {
|
||||||
addReturnBuilder(
|
resultSetMapping.addResultBuilder( Builders.scalar( columnAlias, (BasicType<?>) type ) );
|
||||||
() -> new NativeSQLQueryScalarReturn( columnAlias, type )
|
|
||||||
);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addReturnBuilder(NativeQueryReturnBuilder builder) {
|
@Override
|
||||||
if ( queryReturnBuilders == null ) {
|
public EntityResultBuilder addRoot(String tableAlias, String entityName) {
|
||||||
queryReturnBuilders = new ArrayList<>();
|
final EntityResultBuilder resultBuilder = Builders.entity(
|
||||||
}
|
tableAlias,
|
||||||
|
entityName
|
||||||
queryReturnBuilders.add( builder );
|
);
|
||||||
|
resultSetMapping.addResultBuilder( resultBuilder );
|
||||||
|
return resultBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RootReturn addRoot(String tableAlias, String entityName) {
|
public EntityResultBuilder addRoot(String tableAlias, Class entityType) {
|
||||||
NativeQueryReturnBuilderRootImpl builder = new NativeQueryReturnBuilderRootImpl( tableAlias, entityName );
|
|
||||||
addReturnBuilder( builder );
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RootReturn addRoot(String tableAlias, Class entityType) {
|
|
||||||
return addRoot( tableAlias, entityType.getName() );
|
return addRoot( tableAlias, entityType.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,9 +533,9 @@ public class NativeQueryImpl<R>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FetchReturn addFetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
|
public FetchReturn addFetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
|
||||||
NativeQueryReturnBuilderFetchImpl builder = new NativeQueryReturnBuilderFetchImpl( tableAlias, ownerTableAlias, joinPropertyName );
|
final LegacyFetchBuilder fetchBuilder = Builders.fetch( tableAlias, ownerTableAlias, joinPropertyName );
|
||||||
addReturnBuilder( builder );
|
resultSetMapping.addLegacyFetchBuilder( fetchBuilder );
|
||||||
return builder;
|
return fetchBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.sql.internal;
|
package org.hibernate.query.sql.internal;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -14,7 +15,13 @@ import org.hibernate.ScrollMode;
|
||||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||||
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
||||||
import org.hibernate.query.sql.spi.NativeSelectQueryPlan;
|
import org.hibernate.query.sql.spi.NativeSelectQueryPlan;
|
||||||
|
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
|
||||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBinder;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcSelect;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcSelectExecutor;
|
||||||
|
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
|
||||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||||
import org.hibernate.sql.results.spi.RowTransformer;
|
import org.hibernate.sql.results.spi.RowTransformer;
|
||||||
|
|
||||||
|
@ -40,28 +47,53 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
|
||||||
this.affectedTableNames = affectedTableNames;
|
this.affectedTableNames = affectedTableNames;
|
||||||
this.parameterList = parameterList;
|
this.parameterList = parameterList;
|
||||||
this.resultSetMapping = resultSetMapping;
|
this.resultSetMapping = resultSetMapping;
|
||||||
this.rowTransformer = rowTransformer;
|
this.rowTransformer = rowTransformer != null
|
||||||
|
? rowTransformer
|
||||||
|
: RowTransformerPassThruImpl.instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<R> performList(ExecutionContext executionContext) {
|
public List<R> performList(ExecutionContext executionContext) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
final List<JdbcParameterBinder> jdbcParameterBinders = resolveJdbcParamBinders( executionContext );
|
||||||
|
final JdbcParameterBindings jdbcParameterBindings = resolveJdbcParamBindings( executionContext, jdbcParameterBinders );
|
||||||
|
|
||||||
// final List<JdbcParameterBinder> jdbcParameterBinders = resolveJdbcParameterBinders( executionContext );
|
final JdbcSelect jdbcSelect = new JdbcSelect(
|
||||||
//
|
sql,
|
||||||
// final JdbcSelect jdbcSelect = new JdbcSelectImpl(
|
jdbcParameterBinders,
|
||||||
// sql,
|
resultSetMapping,
|
||||||
// jdbcParameterBinders,
|
affectedTableNames,
|
||||||
// resultSetMapping,
|
Collections.emptySet()
|
||||||
// affectedTableNames
|
);
|
||||||
// );
|
|
||||||
//
|
final JdbcSelectExecutor executor = JdbcSelectExecutorStandardImpl.INSTANCE;
|
||||||
// // todo (6.0) : need to make this swappable (see note in executor class)
|
|
||||||
// final JdbcSelectExecutor executor = JdbcSelectExecutorStandardImpl.INSTANCE;
|
return executor.list(
|
||||||
//
|
jdbcSelect,
|
||||||
// return executor.list( jdbcSelect, JdbcParameterBindings.NO_BINDINGS, executionContext, rowTransformer );
|
jdbcParameterBindings,
|
||||||
|
executionContext,
|
||||||
|
rowTransformer,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
//
|
|
||||||
|
private List<JdbcParameterBinder> resolveJdbcParamBinders(ExecutionContext executionContext) {
|
||||||
|
if ( parameterList == null || parameterList.isEmpty() ) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private JdbcParameterBindings resolveJdbcParamBindings(
|
||||||
|
ExecutionContext executionContext,
|
||||||
|
List<JdbcParameterBinder> jdbcParameterBinders) {
|
||||||
|
if ( jdbcParameterBinders.isEmpty() ) {
|
||||||
|
return JdbcParameterBindings.NO_BINDINGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotYetImplementedFor6Exception( getClass() );
|
||||||
|
}
|
||||||
|
|
||||||
// private List<JdbcParameterBinder> resolveJdbcParameterBinders(ExecutionContext executionContext) {
|
// private List<JdbcParameterBinder> resolveJdbcParameterBinders(ExecutionContext executionContext) {
|
||||||
// final List<JdbcParameterBinder> jdbcParameterBinders = CollectionHelper.arrayList( parameterList.size() );
|
// final List<JdbcParameterBinder> jdbcParameterBinders = CollectionHelper.arrayList( parameterList.size() );
|
||||||
//
|
//
|
||||||
|
@ -98,27 +130,25 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScrollableResultsImplementor<R> performScroll(ScrollMode scrollMode, ExecutionContext executionContext) {
|
public ScrollableResultsImplementor<R> performScroll(ScrollMode scrollMode, ExecutionContext executionContext) {
|
||||||
throw new NotYetImplementedFor6Exception( getClass() );
|
final List<JdbcParameterBinder> jdbcParameterBinders = resolveJdbcParamBinders( executionContext );
|
||||||
//
|
final JdbcParameterBindings jdbcParameterBindings = resolveJdbcParamBindings( executionContext, jdbcParameterBinders );
|
||||||
// // todo (6.0) : see notes above in `#performList`
|
|
||||||
//
|
final JdbcSelect jdbcSelect = new JdbcSelect(
|
||||||
// final List<JdbcParameterBinder> jdbcParameterBinders = resolveJdbcParameterBinders( executionContext );
|
sql,
|
||||||
//
|
jdbcParameterBinders,
|
||||||
// final JdbcSelect jdbcSelect = new JdbcSelectImpl(
|
resultSetMapping,
|
||||||
// sql,
|
affectedTableNames,
|
||||||
// jdbcParameterBinders,
|
Collections.emptySet()
|
||||||
// resultSetMapping,
|
);
|
||||||
// affectedTableNames
|
|
||||||
// );
|
final JdbcSelectExecutor executor = JdbcSelectExecutorStandardImpl.INSTANCE;
|
||||||
// final JdbcSelectExecutor executor = JdbcSelectExecutorStandardImpl.INSTANCE;
|
|
||||||
//
|
return executor.scroll(
|
||||||
// return executor.scroll(
|
jdbcSelect,
|
||||||
// jdbcSelect,
|
scrollMode,
|
||||||
// scrollMode,
|
jdbcParameterBindings,
|
||||||
// // the binders created here encapsulate their bind value
|
executionContext,
|
||||||
// JdbcParameterBindings.NO_BINDINGS,
|
rowTransformer
|
||||||
// executionContext,
|
);
|
||||||
// rowTransformer
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.query.QueryParameter;
|
||||||
import org.hibernate.query.ResultListTransformer;
|
import org.hibernate.query.ResultListTransformer;
|
||||||
import org.hibernate.query.TupleTransformer;
|
import org.hibernate.query.TupleTransformer;
|
||||||
import org.hibernate.query.named.NameableQuery;
|
import org.hibernate.query.named.NameableQuery;
|
||||||
|
import org.hibernate.query.results.EntityResultBuilder;
|
||||||
import org.hibernate.query.spi.QueryImplementor;
|
import org.hibernate.query.spi.QueryImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,7 +56,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
|
||||||
NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType type);
|
NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType type);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
RootReturn addRoot(String tableAlias, String entityName);
|
EntityResultBuilder addRoot(String tableAlias, String entityName);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
NativeQueryImplementor<R> addEntity(String entityName);
|
NativeQueryImplementor<R> addEntity(String entityName);
|
||||||
|
|
|
@ -707,7 +707,7 @@ public abstract class BaseSqmToSqlAstConverter
|
||||||
// add any additional join restrictions
|
// add any additional join restrictions
|
||||||
if ( sqmJoin.getJoinPredicate() != null ) {
|
if ( sqmJoin.getJoinPredicate() != null ) {
|
||||||
if ( sqmJoin.isFetched() ) {
|
if ( sqmJoin.isFetched() ) {
|
||||||
QueryLogger.QUERY_LOGGER.debugf( "Join fetch [" + sqmJoin.getNavigablePath() + "] is restricted" );
|
QueryLogger.QUERY_MESSAGE_LOGGER.debugf( "Join fetch [" + sqmJoin.getNavigablePath() + "] is restricted" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( joinedTableGroupJoin == null ) {
|
if ( joinedTableGroupJoin == null ) {
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.results.jdbc.spi;
|
package org.hibernate.sql.results.jdbc.spi;
|
||||||
|
|
||||||
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.query.spi.ResultSetMapping;
|
import org.hibernate.query.results.ResultSetMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Producer for JdbcValuesMapping references.
|
* Producer for JdbcValuesMapping references.
|
||||||
|
@ -20,13 +21,12 @@ import org.hibernate.query.spi.ResultSetMapping;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
@Incubating
|
||||||
public interface JdbcValuesMappingProducer {
|
public interface JdbcValuesMappingProducer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the selections (both at the JDBC and object level) for this
|
* Resolve the JdbcValuesMapping. This involves resolving the
|
||||||
* mapping. Acts as delayed access to this resolution process to support
|
* {@link org.hibernate.sql.results.graph.DomainResult} and
|
||||||
* "auto discovery" as needed for "undefined scalar" results as defined by
|
* {@link org.hibernate.sql.results.graph.Fetch}
|
||||||
* native-sql and procedure call queries.
|
|
||||||
*/
|
*/
|
||||||
JdbcValuesMapping resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory);
|
JdbcValuesMapping resolve(JdbcValuesMetadata jdbcResultsMetadata, SessionFactoryImplementor sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,12 @@ import javax.persistence.Id;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
import org.hibernate.graph.GraphParser;
|
||||||
import org.hibernate.graph.GraphSemantic;
|
import org.hibernate.graph.GraphSemantic;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
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.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -81,6 +83,7 @@ public class EntityGraphNativeQueryTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@FailureExpected( reason = "Uses an implicit entity/root return, which is not yet implemented" )
|
||||||
void testNativeQueryLoadGraph(SessionFactoryScope scope) {
|
void testNativeQueryLoadGraph(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
|
@ -98,14 +101,21 @@ public class EntityGraphNativeQueryTest {
|
||||||
.setHint( GraphSemantic.LOAD.getJpaHintName(), fooGraph )
|
.setHint( GraphSemantic.LOAD.getJpaHintName(), fooGraph )
|
||||||
.getSingleResult();
|
.getSingleResult();
|
||||||
fail("Should throw exception");
|
fail("Should throw exception");
|
||||||
} catch (Exception e) {
|
}
|
||||||
assertThat( e.getMessage(), is( "A native SQL query cannot use EntityGraphs" ) );
|
catch (Exception e) {
|
||||||
|
if ( e.getMessage().equals( "A native SQL query cannot use EntityGraphs" ) ) {
|
||||||
|
// success
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException( "Unexpected exception", e );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@FailureExpected( reason = "Uses an implicit entity/root return, which is not yet implemented" )
|
||||||
void testNativeQueryFetchGraph(SessionFactoryScope scope) {
|
void testNativeQueryFetchGraph(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
|
@ -123,8 +133,14 @@ public class EntityGraphNativeQueryTest {
|
||||||
.setHint( GraphSemantic.FETCH.getJpaHintName(), fooGraph )
|
.setHint( GraphSemantic.FETCH.getJpaHintName(), fooGraph )
|
||||||
.getSingleResult();
|
.getSingleResult();
|
||||||
fail( "Should throw exception" );
|
fail( "Should throw exception" );
|
||||||
} catch (Exception e) {
|
}
|
||||||
assertThat( e.getMessage(), is( "A native SQL query cannot use EntityGraphs" ) );
|
catch (Exception e) {
|
||||||
|
if ( e.getMessage().equals( "A native SQL query cannot use EntityGraphs" ) ) {
|
||||||
|
// success
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException( "Unexpected exception", e );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,6 +8,8 @@ package org.hibernate.orm.test.query.named.resultmapping;
|
||||||
|
|
||||||
import org.hibernate.query.named.NamedQueryRepository;
|
import org.hibernate.query.named.NamedQueryRepository;
|
||||||
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
|
import org.hibernate.query.results.ResultSetMapping;
|
||||||
|
import org.hibernate.query.results.ResultSetMappingImpl;
|
||||||
import org.hibernate.query.spi.QueryEngine;
|
import org.hibernate.query.spi.QueryEngine;
|
||||||
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
@ -16,7 +18,7 @@ import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,8 +33,10 @@ public class SimpleNamedMappingTests {
|
||||||
final QueryEngine queryEngine = sessionFactoryScope.getSessionFactory().getQueryEngine();
|
final QueryEngine queryEngine = sessionFactoryScope.getSessionFactory().getQueryEngine();
|
||||||
final NamedQueryRepository namedQueryRepository = queryEngine.getNamedQueryRepository();
|
final NamedQueryRepository namedQueryRepository = queryEngine.getNamedQueryRepository();
|
||||||
final NamedResultSetMappingMemento mappingMemento = namedQueryRepository.getResultSetMappingMemento( "name" );
|
final NamedResultSetMappingMemento mappingMemento = namedQueryRepository.getResultSetMappingMemento( "name" );
|
||||||
assertThat( mappingMemento.toResultSetMapping(), notNullValue() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo (6.0) : atm that ^^ is as far as we can test until we implement native-query support to test applying a mapping
|
final ResultSetMapping mapping = new ResultSetMappingImpl();
|
||||||
|
mappingMemento.resolve( mapping, querySpace -> {}, sessionFactoryScope.getSessionFactory() );
|
||||||
|
|
||||||
|
assertThat( mapping.getNumberOfResultBuilders(), is( 1 ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* 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.sql;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||||
|
import org.hibernate.testing.orm.domain.contacts.Contact;
|
||||||
|
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.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.hamcrest.CoreMatchers;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@DomainModel(
|
||||||
|
standardModels = StandardDomainModel.CONTACTS
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class NativeQueryScalarTests {
|
||||||
|
@Test
|
||||||
|
public void fullyImplicitTest(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final String sql = "select gender, first, last, id from contacts";
|
||||||
|
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||||
|
|
||||||
|
final List<?> results = query.list();
|
||||||
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
final Object result = results.get( 0 );
|
||||||
|
assertThat( result, instanceOf( Object[].class ) );
|
||||||
|
|
||||||
|
final Object[] values = (Object[]) result;
|
||||||
|
assertThat( values.length, is(4 ) );
|
||||||
|
|
||||||
|
assertThat( ( (Number) values[0] ).intValue(), is( Contact.Gender.OTHER.ordinal() ) );
|
||||||
|
assertThat( values[1], is( "My First" ) );
|
||||||
|
assertThat( values[2], is( "Contact" ) );
|
||||||
|
assertThat( values[3], is( 1 ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void explicitOrderTest(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final String sql = "select gender, first, last, id from contacts";
|
||||||
|
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||||
|
// notice the reverse order from the select clause
|
||||||
|
query.addScalar( "id" );
|
||||||
|
query.addScalar( "last" );
|
||||||
|
query.addScalar( "first" );
|
||||||
|
query.addScalar( "gender" );
|
||||||
|
|
||||||
|
final List<?> results = query.list();
|
||||||
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
final Object result = results.get( 0 );
|
||||||
|
assertThat( result, instanceOf( Object[].class ) );
|
||||||
|
|
||||||
|
final Object[] values = (Object[]) result;
|
||||||
|
assertThat( values.length, is(4 ) );
|
||||||
|
|
||||||
|
assertThat( values[0], is( 1 ) );
|
||||||
|
assertThat( values[1], is( "Contact" ) );
|
||||||
|
assertThat( values[2], is( "My First" ) );
|
||||||
|
assertThat( ( (Number) values[3] ).intValue(), is( Contact.Gender.OTHER.ordinal() ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@FailureExpected( reason = "Explicit type support not working atm" )
|
||||||
|
public void explicitEnumTypeTest(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
final String sql = "select gender, first, last, id from contacts";
|
||||||
|
final NativeQueryImplementor<?> query = session.createNativeQuery( sql );
|
||||||
|
// notice the reverse order from the select clause
|
||||||
|
query.addScalar( "id" );
|
||||||
|
query.addScalar( "last" );
|
||||||
|
query.addScalar( "first" );
|
||||||
|
query.addScalar( "gender", scope.getSessionFactory().getTypeConfiguration().getBasicTypeForJavaType( Contact.Gender.class ) );
|
||||||
|
|
||||||
|
final List<?> results = query.list();
|
||||||
|
assertThat( results.size(), is( 1 ) );
|
||||||
|
final Object result = results.get( 0 );
|
||||||
|
assertThat( result, instanceOf( Object[].class ) );
|
||||||
|
|
||||||
|
final Object[] values = (Object[]) result;
|
||||||
|
assertThat( values.length, is(4 ) );
|
||||||
|
|
||||||
|
assertThat( values[0], is( 1 ) );
|
||||||
|
assertThat( values[1], is( "Contact" ) );
|
||||||
|
assertThat( values[2], is( "My First" ) );
|
||||||
|
assertThat( values[3], is( Contact.Gender.OTHER ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void prepareData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
session.persist(
|
||||||
|
new Contact(
|
||||||
|
1,
|
||||||
|
new Contact.Name( "My First", "Contact"),
|
||||||
|
Contact.Gender.OTHER,
|
||||||
|
LocalDate.EPOCH
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void cleanUpData(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> session.createQuery( "delete Contact" ).executeUpdate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link org.hibernate.query.NativeQuery}
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.query.sql;
|
|
@ -10,13 +10,17 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.persistence.CollectionTable;
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.ColumnResult;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.SqlResultSetMapping;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.query.NativeQuery;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -117,8 +121,43 @@ public class SetElementNullBasicTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// @SqlResultSetMapping(
|
||||||
|
// columns = {
|
||||||
|
// @ColumnResult( name = "a_id", type = long.class ),
|
||||||
|
// @ColumnResult( name = "a_name" )
|
||||||
|
// }
|
||||||
|
// )
|
||||||
private List<?> getCollectionElementRows(int id) {
|
private List<?> getCollectionElementRows(int id) {
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final String qry = "SELECT a.id as a_id, a.name as a_name FROM AnEntity a where a.id = " + id;
|
||||||
|
final NativeQuery nativeQuery = session.createNativeQuery( qry );
|
||||||
|
nativeQuery.list();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
nativeQuery.addRoot( "a", AnEntity.class )
|
||||||
|
.addIdColumnAliases( "a_id" )
|
||||||
|
.addProperty( "name", "a_name" );
|
||||||
|
nativeQuery.addFetch( "c", "a", "aCollection" );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
doInHibernate(
|
||||||
|
this::sessionFactory,
|
||||||
|
session -> {
|
||||||
|
final String qry = "SELECT a.id as a_id, a.name as a_name, c.aCollection FROM AnEntity a join AnEntity_aCollection c on a.id = c.id and a.id = " + id;
|
||||||
|
final NativeQuery nativeQuery = session.createNativeQuery( qry );
|
||||||
|
nativeQuery.addRoot( "a", AnEntity.class )
|
||||||
|
.addIdColumnAliases( "a_id" )
|
||||||
|
.addProperty( "name", "a_name" );
|
||||||
|
nativeQuery.addFetch( "c", "a", "aCollection" );
|
||||||
|
nativeQuery.list();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return doInHibernate(
|
return doInHibernate(
|
||||||
this::sessionFactory, session -> {
|
this::sessionFactory, session -> {
|
||||||
return session.createNativeQuery(
|
return session.createNativeQuery(
|
||||||
|
|
|
@ -16,6 +16,7 @@ import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.OrderColumn;
|
import javax.persistence.OrderColumn;
|
||||||
import javax.persistence.SecondaryTable;
|
import javax.persistence.SecondaryTable;
|
||||||
|
import javax.persistence.Table;
|
||||||
import javax.persistence.Temporal;
|
import javax.persistence.Temporal;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ import javax.persistence.TemporalType;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
|
@Table( name = "contacts" )
|
||||||
@SecondaryTable( name="contact_supp" )
|
@SecondaryTable( name="contact_supp" )
|
||||||
public class Contact {
|
public class Contact {
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
|
|
@ -41,6 +41,15 @@ public class SimpleEntity {
|
||||||
this.someString = someString;
|
this.someString = someString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SimpleEntity(
|
||||||
|
Integer id,
|
||||||
|
String someString,
|
||||||
|
Long someLong) {
|
||||||
|
this.id = id;
|
||||||
|
this.someString = someString;
|
||||||
|
this.someLong = someLong;
|
||||||
|
}
|
||||||
|
|
||||||
public SimpleEntity(
|
public SimpleEntity(
|
||||||
Integer id,
|
Integer id,
|
||||||
Date someDate,
|
Date someDate,
|
||||||
|
|
Loading…
Reference in New Issue