Fix some stored procedure and native query issues
This commit is contained in:
parent
8ed1ed5159
commit
439788198f
|
@ -7,13 +7,15 @@ import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.EntityResult;
|
import jakarta.persistence.EntityResult;
|
||||||
import jakarta.persistence.FieldResult;
|
import jakarta.persistence.FieldResult;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.NamedStoredProcedureQuery;
|
||||||
|
import jakarta.persistence.QueryHint;
|
||||||
import jakarta.persistence.SqlResultSetMapping;
|
import jakarta.persistence.SqlResultSetMapping;
|
||||||
import jakarta.persistence.SqlResultSetMappings;
|
import jakarta.persistence.SqlResultSetMappings;
|
||||||
|
import jakarta.persistence.StoredProcedureParameter;
|
||||||
|
|
||||||
import org.hibernate.annotations.NamedNativeQuery;
|
|
||||||
import org.hibernate.c3p0.internal.C3P0ConnectionProvider;
|
import org.hibernate.c3p0.internal.C3P0ConnectionProvider;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.dialect.Oracle8iDialect;
|
import org.hibernate.dialect.OracleDialect;
|
||||||
|
|
||||||
import org.hibernate.testing.RequiresDialect;
|
import org.hibernate.testing.RequiresDialect;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
@ -27,7 +29,7 @@ import static org.junit.Assert.assertEquals;
|
||||||
/**
|
/**
|
||||||
* @author Vlad Mihalcea
|
* @author Vlad Mihalcea
|
||||||
*/
|
*/
|
||||||
@RequiresDialect(Oracle8iDialect.class)
|
@RequiresDialect(OracleDialect.class)
|
||||||
@TestForIssue( jiraKey = "HHH-10256" )
|
@TestForIssue( jiraKey = "HHH-10256" )
|
||||||
public class OracleSQLCallableStatementProxyTest extends
|
public class OracleSQLCallableStatementProxyTest extends
|
||||||
BaseCoreFunctionalTestCase {
|
BaseCoreFunctionalTestCase {
|
||||||
|
@ -95,19 +97,19 @@ public class OracleSQLCallableStatementProxyTest extends
|
||||||
public void testStoredProcedureOutParameter() {
|
public void testStoredProcedureOutParameter() {
|
||||||
doInHibernate( this::sessionFactory, session -> {
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
List<Object[]> persons = session
|
List<Object[]> persons = session
|
||||||
.createNamedQuery(
|
.createNamedStoredProcedureQuery( "getPerson" )
|
||||||
"getPerson")
|
|
||||||
.setParameter(1, 1L)
|
.setParameter(1, 1L)
|
||||||
.getResultList();
|
.getResultList();
|
||||||
assertEquals(1, persons.size());
|
assertEquals(1, persons.size());
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@NamedNativeQuery(
|
@NamedStoredProcedureQuery(
|
||||||
name = "getPerson",
|
name = "getPerson",
|
||||||
query = "{ ? = call fn_person( ? ) }",
|
procedureName = "fn_person",
|
||||||
callable = true,
|
resultSetMappings = "person",
|
||||||
resultSetMapping = "person"
|
hints = @QueryHint(name = "org.hibernate.callableFunction", value = "true"),
|
||||||
|
parameters = @StoredProcedureParameter(type = Long.class)
|
||||||
)
|
)
|
||||||
@SqlResultSetMappings({
|
@SqlResultSetMappings({
|
||||||
@SqlResultSetMapping(
|
@SqlResultSetMapping(
|
||||||
|
|
|
@ -153,7 +153,7 @@ public class Identifier implements Comparable<Identifier> {
|
||||||
public static String unQuote(String name) {
|
public static String unQuote(String name) {
|
||||||
assert isQuoted( name );
|
assert isQuoted( name );
|
||||||
|
|
||||||
return name.substring( 1, name.length() - 2 );
|
return name.substring( 1, name.length() - 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -288,9 +288,6 @@ public class MetadataBuildingProcess {
|
||||||
processor.postProcessEntityHierarchies();
|
processor.postProcessEntityHierarchies();
|
||||||
|
|
||||||
processor.processResultSetMappings();
|
processor.processResultSetMappings();
|
||||||
processor.processNamedQueries();
|
|
||||||
|
|
||||||
processor.finishUp();
|
|
||||||
|
|
||||||
for ( MetadataContributor contributor : classLoaderService.loadJavaServices( MetadataContributor.class ) ) {
|
for ( MetadataContributor contributor : classLoaderService.loadJavaServices( MetadataContributor.class ) ) {
|
||||||
log.tracef( "Calling MetadataContributor : %s", contributor );
|
log.tracef( "Calling MetadataContributor : %s", contributor );
|
||||||
|
@ -299,6 +296,11 @@ public class MetadataBuildingProcess {
|
||||||
|
|
||||||
metadataCollector.processSecondPasses( rootMetadataBuildingContext );
|
metadataCollector.processSecondPasses( rootMetadataBuildingContext );
|
||||||
|
|
||||||
|
// Make sure collections are fully bound before processing named queries as hbm result set mappings require it
|
||||||
|
processor.processNamedQueries();
|
||||||
|
|
||||||
|
processor.finishUp();
|
||||||
|
|
||||||
if ( options.isXmlMappingEnabled() ) {
|
if ( options.isXmlMappingEnabled() ) {
|
||||||
final Iterable<AdditionalJaxbMappingProducer> producers = classLoaderService.loadJavaServices( AdditionalJaxbMappingProducer.class );
|
final Iterable<AdditionalJaxbMappingProducer> producers = classLoaderService.loadJavaServices( AdditionalJaxbMappingProducer.class );
|
||||||
if ( producers != null ) {
|
if ( producers != null ) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
@ -27,11 +28,23 @@ import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmResultSetMappingType;
|
||||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
|
import org.hibernate.mapping.Collection;
|
||||||
|
import org.hibernate.mapping.Component;
|
||||||
|
import org.hibernate.mapping.IndexedCollection;
|
||||||
|
import org.hibernate.mapping.OneToMany;
|
||||||
|
import org.hibernate.mapping.PersistentClass;
|
||||||
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.mapping.ToOne;
|
||||||
|
import org.hibernate.mapping.Value;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
import org.hibernate.query.internal.FetchMementoEmbeddableStandard;
|
||||||
|
import org.hibernate.query.internal.FetchMementoEntityStandard;
|
||||||
import org.hibernate.query.spi.NavigablePath;
|
import org.hibernate.query.spi.NavigablePath;
|
||||||
import org.hibernate.query.internal.FetchMementoBasicStandard;
|
import org.hibernate.query.internal.FetchMementoBasicStandard;
|
||||||
import org.hibernate.query.internal.FetchMementoHbmStandard;
|
import org.hibernate.query.internal.FetchMementoHbmStandard;
|
||||||
|
@ -47,6 +60,7 @@ import org.hibernate.query.named.NamedResultSetMappingMemento;
|
||||||
import org.hibernate.query.named.ResultMemento;
|
import org.hibernate.query.named.ResultMemento;
|
||||||
import org.hibernate.sql.results.graph.Fetchable;
|
import org.hibernate.sql.results.graph.Fetchable;
|
||||||
import org.hibernate.sql.results.graph.FetchableContainer;
|
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||||
|
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -498,6 +512,21 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
||||||
this.propertyPathParts = propertyPath.split( "\\." );
|
this.propertyPathParts = propertyPath.split( "\\." );
|
||||||
this.columnAliases = extractColumnAliases( hbmPropertyMapping, context );
|
this.columnAliases = extractColumnAliases( hbmPropertyMapping, context );
|
||||||
|
|
||||||
|
if ( columnAliases.size() > 1 ) {
|
||||||
|
// We have to reorder the columns according to the property reordering
|
||||||
|
final Value value = getValue( parent, propertyPath, context );
|
||||||
|
assert value instanceof Component;
|
||||||
|
final Component component = (Component) value;
|
||||||
|
int[] originalPropertyOrder = component.sortProperties();
|
||||||
|
if ( originalPropertyOrder != null ) {
|
||||||
|
final String[] originalColumns = columnAliases.toArray( new String[0] );
|
||||||
|
for ( int i = 0; i < originalPropertyOrder.length; i++ ) {
|
||||||
|
final int originalIndex = originalPropertyOrder[i];
|
||||||
|
columnAliases.set( i, originalColumns[originalIndex] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BootQueryLogging.LOGGER.debugf(
|
BootQueryLogging.LOGGER.debugf(
|
||||||
"Creating PropertyFetchDescriptor (%s : %s) for ResultSet mapping - %s",
|
"Creating PropertyFetchDescriptor (%s : %s) for ResultSet mapping - %s",
|
||||||
parent,
|
parent,
|
||||||
|
@ -506,11 +535,100 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Value getValue(HbmFetchParent parent, String propertyPath, MetadataBuildingContext context) {
|
||||||
|
if ( parent instanceof EntityResultDescriptor ) {
|
||||||
|
final PersistentClass entityBinding = context.getMetadataCollector()
|
||||||
|
.getEntityBinding( ( (EntityResultDescriptor) parent ).entityName );
|
||||||
|
Value value = null;
|
||||||
|
StringTokenizer st = new StringTokenizer( propertyPath, ".", false );
|
||||||
|
try {
|
||||||
|
while ( st.hasMoreElements() ) {
|
||||||
|
final String element = (String) st.nextElement();
|
||||||
|
if ( value == null ) {
|
||||||
|
Property identifierProperty = entityBinding.getIdentifierProperty();
|
||||||
|
if ( identifierProperty != null && identifierProperty.getName().equals( element ) ) {
|
||||||
|
// we have a mapped identifier property and the root of
|
||||||
|
// the incoming property path matched that identifier
|
||||||
|
// property
|
||||||
|
value = identifierProperty.getValue();
|
||||||
|
}
|
||||||
|
else if ( identifierProperty == null && entityBinding.getIdentifierMapper() != null ) {
|
||||||
|
// we have an embedded composite identifier
|
||||||
|
try {
|
||||||
|
identifierProperty = entityBinding.getIdentifierMapper().getProperty( element );
|
||||||
|
// the root of the incoming property path matched one
|
||||||
|
// of the embedded composite identifier properties
|
||||||
|
value = identifierProperty.getValue();
|
||||||
|
}
|
||||||
|
catch (MappingException ignore) {
|
||||||
|
// ignore it...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( value == null ) {
|
||||||
|
value = entityBinding.getProperty( element ).getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( value instanceof Component ) {
|
||||||
|
value = ( (Component) value ).getProperty( element ).getValue();
|
||||||
|
}
|
||||||
|
else if ( value instanceof ToOne ) {
|
||||||
|
value = context.getMetadataCollector()
|
||||||
|
.getEntityBinding( ( (ToOne) value ).getReferencedEntityName() )
|
||||||
|
.getProperty( element )
|
||||||
|
.getValue();
|
||||||
|
}
|
||||||
|
else if ( value instanceof OneToMany ) {
|
||||||
|
value = ( (OneToMany) value ).getAssociatedClass().getProperty( element ).getValue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final Collection collection = (Collection) value;
|
||||||
|
switch ( element ) {
|
||||||
|
case "key":
|
||||||
|
value = collection.getKey();
|
||||||
|
break;
|
||||||
|
case "element":
|
||||||
|
value = collection.getElement();
|
||||||
|
break;
|
||||||
|
case "index":
|
||||||
|
if ( collection instanceof IndexedCollection ) {
|
||||||
|
value = ( (IndexedCollection) collection ).getIndex();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new MappingException( "property [" + element + "] not found on collection [" + collection.getRole() + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
catch (MappingException e) {
|
||||||
|
throw new MappingException( "property [" + propertyPath + "] not found on entity [" + entityBinding.getEntityName() + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( parent instanceof CollectionResultDescriptor ) {
|
||||||
|
final Collection collectionBinding = context.getMetadataCollector()
|
||||||
|
.getCollectionBinding( ( (CollectionResultDescriptor) parent ).collectionPath.getFullPath() );
|
||||||
|
return collectionBinding.getElement();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert parent instanceof JoinDescriptor;
|
||||||
|
final JoinDescriptor joinDescriptor = (JoinDescriptor) parent;
|
||||||
|
final HbmFetchParent joinParent = joinDescriptor.fetchParentByAliasAccess.get()
|
||||||
|
.get( joinDescriptor.ownerTableAlias );
|
||||||
|
return getValue( joinParent, joinDescriptor.propertyPath + "." + propertyPath, context );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFetchablePath() {
|
public String getFetchablePath() {
|
||||||
return propertyPath;
|
return propertyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getColumnAliases() {
|
||||||
|
return columnAliases;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<String> extractColumnAliases(
|
private static List<String> extractColumnAliases(
|
||||||
JaxbHbmNativeQueryPropertyReturnType hbmPropertyMapping,
|
JaxbHbmNativeQueryPropertyReturnType hbmPropertyMapping,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
|
@ -520,7 +638,7 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
||||||
|
|
||||||
final List<String> columnAliases = new ArrayList<>( hbmPropertyMapping.getReturnColumn().size() );
|
final List<String> columnAliases = new ArrayList<>( hbmPropertyMapping.getReturnColumn().size() );
|
||||||
hbmPropertyMapping.getReturnColumn().forEach(
|
hbmPropertyMapping.getReturnColumn().forEach(
|
||||||
(column) -> columnAliases.add( column.getName() )
|
column -> columnAliases.add( column.getName() )
|
||||||
);
|
);
|
||||||
return columnAliases;
|
return columnAliases;
|
||||||
}
|
}
|
||||||
|
@ -552,7 +670,28 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
||||||
fetchable = (Fetchable) ( (FetchableContainer) fetchable ).findSubPart( propertyPathParts[i], null );
|
fetchable = (Fetchable) ( (FetchableContainer) fetchable ).findSubPart( propertyPathParts[i], null );
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FetchMementoBasicStandard( navigablePath, (BasicValuedModelPart) fetchable, columnAliases.get( 0 ) );
|
if ( fetchable instanceof BasicValuedModelPart ) {
|
||||||
|
return new FetchMementoBasicStandard(
|
||||||
|
navigablePath,
|
||||||
|
(BasicValuedModelPart) fetchable,
|
||||||
|
columnAliases.get( 0 )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( fetchable instanceof EntityValuedFetchable ) {
|
||||||
|
return new FetchMementoEntityStandard(
|
||||||
|
navigablePath,
|
||||||
|
(EntityValuedFetchable) fetchable,
|
||||||
|
columnAliases
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert fetchable instanceof EmbeddableValuedModelPart;
|
||||||
|
return new FetchMementoEmbeddableStandard(
|
||||||
|
navigablePath,
|
||||||
|
(EmbeddableValuedModelPart) fetchable,
|
||||||
|
columnAliases
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -632,16 +771,26 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
||||||
applyFetchJoins( joinDescriptorsAccess, tableAlias, propertyFetchDescriptors );
|
applyFetchJoins( joinDescriptorsAccess, tableAlias, propertyFetchDescriptors );
|
||||||
|
|
||||||
final Map<String, FetchMemento> fetchDescriptorMap = new HashMap<>();
|
final Map<String, FetchMemento> fetchDescriptorMap = new HashMap<>();
|
||||||
|
final List<String> keyColumnNames = new ArrayList<>();
|
||||||
|
final boolean isPlural = thisAsParentMemento.getFetchableContainer() instanceof PluralAttributeMapping;
|
||||||
propertyFetchDescriptors.forEach(
|
propertyFetchDescriptors.forEach(
|
||||||
hbmFetchDescriptor -> fetchDescriptorMap.put(
|
hbmFetchDescriptor -> {
|
||||||
|
if ( isPlural && "key".equals( hbmFetchDescriptor.getFetchablePath() ) ) {
|
||||||
|
keyColumnNames.addAll( ( (PropertyFetchDescriptor) hbmFetchDescriptor ).getColumnAliases() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fetchDescriptorMap.put(
|
||||||
hbmFetchDescriptor.getFetchablePath(),
|
hbmFetchDescriptor.getFetchablePath(),
|
||||||
hbmFetchDescriptor.resolve( resolutionContext )
|
hbmFetchDescriptor.resolve( resolutionContext )
|
||||||
)
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
memento = new FetchMementoHbmStandard(
|
memento = new FetchMementoHbmStandard(
|
||||||
thisAsParentMemento.getNavigablePath(),
|
thisAsParentMemento.getNavigablePath(),
|
||||||
ownerTableAlias,
|
ownerTableAlias,
|
||||||
tableAlias,
|
tableAlias,
|
||||||
|
keyColumnNames,
|
||||||
lockMode,
|
lockMode,
|
||||||
thisAsParentMemento,
|
thisAsParentMemento,
|
||||||
fetchDescriptorMap,
|
fetchDescriptorMap,
|
||||||
|
@ -665,7 +814,14 @@ public class HbmResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
||||||
final FetchParentMemento ownerMemento = hbmFetchParent.resolveParentMemento( resolutionContext );
|
final FetchParentMemento ownerMemento = hbmFetchParent.resolveParentMemento( resolutionContext );
|
||||||
|
|
||||||
final String[] parts = propertyPath.split( "\\." );
|
final String[] parts = propertyPath.split( "\\." );
|
||||||
NavigablePath navigablePath = ownerMemento.getNavigablePath().append( parts[ 0 ] );
|
NavigablePath navigablePath;
|
||||||
|
if ( ownerMemento.getFetchableContainer() instanceof PluralAttributeMapping ) {
|
||||||
|
navigablePath = ownerMemento.getNavigablePath().append( CollectionPart.Nature.ELEMENT.getName() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
navigablePath = ownerMemento.getNavigablePath();
|
||||||
|
}
|
||||||
|
navigablePath = navigablePath.append( parts[ 0 ] );
|
||||||
FetchableContainer fetchable = (FetchableContainer) ownerMemento.getFetchableContainer().findSubPart( parts[ 0 ], null );
|
FetchableContainer fetchable = (FetchableContainer) ownerMemento.getFetchableContainer().findSubPart( parts[ 0 ], null );
|
||||||
|
|
||||||
for ( int i = 1; i < parts.length; i++ ) {
|
for ( int i = 1; i < parts.length; i++ ) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.query;
|
package org.hibernate.boot.query;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -76,10 +77,26 @@ public class NamedNativeQueryDefinitionBuilder extends AbstractNamedQueryBuilder
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSqlString() {
|
||||||
|
return sqlString;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<String> getQuerySpaces() {
|
public Set<String> getQuerySpaces() {
|
||||||
return querySpaces;
|
return querySpaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getParameterTypes() {
|
||||||
|
return parameterTypes == null ? Collections.emptyMap() : parameterTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResultSetMappingName() {
|
||||||
|
return resultSetMappingName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResultSetMappingClassName() {
|
||||||
|
return resultSetMappingClassName;
|
||||||
|
}
|
||||||
|
|
||||||
public NamedNativeQueryDefinitionBuilder addSynchronizedQuerySpaces(Set<String> querySpaces) {
|
public NamedNativeQueryDefinitionBuilder addSynchronizedQuerySpaces(Set<String> querySpaces) {
|
||||||
if ( querySpaces == null || querySpaces.isEmpty() ) {
|
if ( querySpaces == null || querySpaces.isEmpty() ) {
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -1271,6 +1271,12 @@ public class OracleDialect extends Dialect {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsNamedParameters(DatabaseMetaData databaseMetaData) {
|
||||||
|
// Not sure if it's a JDBC driver issue, but it doesn't work
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {
|
public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {
|
||||||
return (ResultSet) statement.getObject( name );
|
return (ResultSet) statement.getObject( name );
|
||||||
|
|
|
@ -884,7 +884,7 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
return exporter;
|
return exporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SqlServerSequenceExporter extends StandardSequenceExporter {
|
private static class SqlServerSequenceExporter extends StandardSequenceExporter {
|
||||||
|
|
||||||
public SqlServerSequenceExporter(Dialect dialect) {
|
public SqlServerSequenceExporter(Dialect dialect) {
|
||||||
super( dialect );
|
super( dialect );
|
||||||
|
@ -900,6 +900,12 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsNamedParameters(DatabaseMetaData databaseMetaData) {
|
||||||
|
// Not sure if it's a JDBC driver issue, but it doesn't work
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String generatedAs(String generatedAs) {
|
public String generatedAs(String generatedAs) {
|
||||||
return " as (" + generatedAs + ") persisted";
|
return " as (" + generatedAs + ") persisted";
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.ast.internal;
|
package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.loader.ast.spi.CollectionLoader;
|
import org.hibernate.loader.ast.spi.CollectionLoader;
|
||||||
|
@ -14,6 +15,8 @@ import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.query.named.NamedQueryMemento;
|
import org.hibernate.query.named.NamedQueryMemento;
|
||||||
import org.hibernate.query.spi.QueryImplementor;
|
import org.hibernate.query.spi.QueryImplementor;
|
||||||
|
|
||||||
|
import jakarta.persistence.Parameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
@ -34,7 +37,9 @@ public class CollectionLoaderNamedQuery implements CollectionLoader {
|
||||||
@Override
|
@Override
|
||||||
public PersistentCollection<?> load(Object key, SharedSessionContractImplementor session) {
|
public PersistentCollection<?> load(Object key, SharedSessionContractImplementor session) {
|
||||||
final QueryImplementor<PersistentCollection<?>> query = namedQueryMemento.toQuery( session );
|
final QueryImplementor<PersistentCollection<?>> query = namedQueryMemento.toQuery( session );
|
||||||
query.setParameter( 1, key );
|
//noinspection unchecked
|
||||||
|
query.setParameter( (Parameter<Object>) query.getParameters().iterator().next(), key );
|
||||||
|
query.setHibernateFlushMode( FlushMode.MANUAL );
|
||||||
return query.getResultList().get( 0 );
|
return query.getResultList().get( 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.ast.internal;
|
package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
@ -14,6 +15,8 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.query.named.NamedQueryMemento;
|
import org.hibernate.query.named.NamedQueryMemento;
|
||||||
import org.hibernate.query.spi.QueryImplementor;
|
import org.hibernate.query.spi.QueryImplementor;
|
||||||
|
|
||||||
|
import jakarta.persistence.Parameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of SingleIdEntityLoader for cases where the application has
|
* Implementation of SingleIdEntityLoader for cases where the application has
|
||||||
* provided the select load query
|
* provided the select load query
|
||||||
|
@ -44,7 +47,9 @@ public class SingleIdEntityLoaderProvidedQueryImpl<T> implements SingleIdEntityL
|
||||||
entityDescriptor.getMappedJavaType().getJavaTypeClass()
|
entityDescriptor.getMappedJavaType().getJavaTypeClass()
|
||||||
);
|
);
|
||||||
|
|
||||||
query.setParameter( 1, pkValue );
|
//noinspection unchecked
|
||||||
|
query.setParameter( (Parameter<Object>) query.getParameters().iterator().next(), pkValue );
|
||||||
|
query.setHibernateFlushMode( FlushMode.MANUAL );
|
||||||
|
|
||||||
return query.uniqueResult();
|
return query.uniqueResult();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2678,7 +2678,7 @@ public abstract class AbstractEntityPersister
|
||||||
Component component = (Component) property.getValue();
|
Component component = (Component) property.getValue();
|
||||||
internalInitSubclassPropertyAliasesMap( name, component.getProperties() );
|
internalInitSubclassPropertyAliasesMap( name, component.getProperties() );
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
String[] aliases = new String[property.getColumnSpan()];
|
String[] aliases = new String[property.getColumnSpan()];
|
||||||
String[] cols = new String[property.getColumnSpan()];
|
String[] cols = new String[property.getColumnSpan()];
|
||||||
int l = 0;
|
int l = 0;
|
||||||
|
@ -2692,7 +2692,6 @@ public abstract class AbstractEntityPersister
|
||||||
subclassPropertyAliases.put( name, aliases );
|
subclassPropertyAliases.put( name, aliases );
|
||||||
subclassPropertyColumnNames.put( name, cols );
|
subclassPropertyColumnNames.put( name, cols );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import java.sql.CallableStatement;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.procedure.spi.CallableStatementSupport;
|
import org.hibernate.procedure.spi.CallableStatementSupport;
|
||||||
import org.hibernate.procedure.spi.ParameterStrategy;
|
|
||||||
import org.hibernate.query.spi.ProcedureParameterMetadataImplementor;
|
import org.hibernate.query.spi.ProcedureParameterMetadataImplementor;
|
||||||
import org.hibernate.sql.exec.spi.JdbcCall;
|
import org.hibernate.sql.exec.spi.JdbcCall;
|
||||||
import org.hibernate.sql.exec.spi.JdbcCallParameterRegistration;
|
import org.hibernate.sql.exec.spi.JdbcCallParameterRegistration;
|
||||||
|
@ -22,7 +21,6 @@ public abstract class AbstractStandardCallableStatementSupport implements Callab
|
||||||
String procedureName,
|
String procedureName,
|
||||||
JdbcCall procedureCall,
|
JdbcCall procedureCall,
|
||||||
CallableStatement statement,
|
CallableStatement statement,
|
||||||
ParameterStrategy parameterStrategy,
|
|
||||||
ProcedureParameterMetadataImplementor parameterMetadata,
|
ProcedureParameterMetadataImplementor parameterMetadata,
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
if ( procedureCall.getFunctionReturn() != null ) {
|
if ( procedureCall.getFunctionReturn() != null ) {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.procedure.spi.ProcedureParameterImplementor;
|
||||||
import org.hibernate.query.spi.ProcedureParameterMetadataImplementor;
|
import org.hibernate.query.spi.ProcedureParameterMetadataImplementor;
|
||||||
import org.hibernate.sql.exec.internal.JdbcCallImpl;
|
import org.hibernate.sql.exec.internal.JdbcCallImpl;
|
||||||
import org.hibernate.sql.exec.spi.JdbcCall;
|
import org.hibernate.sql.exec.spi.JdbcCall;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcCallParameterRegistration;
|
||||||
|
|
||||||
import jakarta.persistence.ParameterMode;
|
import jakarta.persistence.ParameterMode;
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ public class PostgresCallableStatementSupport extends AbstractStandardCallableSt
|
||||||
final boolean firstParamIsRefCursor = parameterMetadata.getParameterCount() != 0
|
final boolean firstParamIsRefCursor = parameterMetadata.getParameterCount() != 0
|
||||||
&& isFirstParameterModeRefCursor( parameterMetadata );
|
&& isFirstParameterModeRefCursor( parameterMetadata );
|
||||||
|
|
||||||
if ( firstParamIsRefCursor ) {
|
if ( firstParamIsRefCursor || functionReturn != null ) {
|
||||||
// validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional)
|
// validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional)
|
||||||
if ( parameterMetadata.hasNamedParameters() ) {
|
if ( parameterMetadata.hasNamedParameters() ) {
|
||||||
throw new HibernateException( "Cannot mix named parameters and REF_CURSOR parameter on PostgreSQL" );
|
throw new HibernateException( "Cannot mix named parameters and REF_CURSOR parameter on PostgreSQL" );
|
||||||
|
@ -46,11 +47,10 @@ public class PostgresCallableStatementSupport extends AbstractStandardCallableSt
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<? extends ProcedureParameterImplementor<?>> registrations = parameterMetadata.getRegistrationsAsList();
|
final List<? extends ProcedureParameterImplementor<?>> registrations = parameterMetadata.getRegistrationsAsList();
|
||||||
final JdbcCallImpl.Builder builder = new JdbcCallImpl.Builder(
|
final ParameterStrategy parameterStrategy = parameterMetadata.hasNamedParameters() ?
|
||||||
parameterMetadata.hasNamedParameters() ?
|
|
||||||
ParameterStrategy.NAMED :
|
ParameterStrategy.NAMED :
|
||||||
ParameterStrategy.POSITIONAL
|
ParameterStrategy.POSITIONAL;
|
||||||
);
|
final JdbcCallImpl.Builder builder = new JdbcCallImpl.Builder( parameterStrategy );
|
||||||
|
|
||||||
final StringBuilder buffer;
|
final StringBuilder buffer;
|
||||||
final int offset;
|
final int offset;
|
||||||
|
@ -82,9 +82,19 @@ public class PostgresCallableStatementSupport extends AbstractStandardCallableSt
|
||||||
throw new HibernateException(
|
throw new HibernateException(
|
||||||
"PostgreSQL supports only one REF_CURSOR parameter, but multiple were registered" );
|
"PostgreSQL supports only one REF_CURSOR parameter, but multiple were registered" );
|
||||||
}
|
}
|
||||||
buffer.append( sep ).append( "?" );
|
buffer.append( sep );
|
||||||
|
final JdbcCallParameterRegistration registration = parameter.toJdbcParameterRegistration(
|
||||||
|
i + offset,
|
||||||
|
procedureCall
|
||||||
|
);
|
||||||
|
if ( registration.getName() != null ) {
|
||||||
|
buffer.append( ':' ).append( registration.getName() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer.append( "?" );
|
||||||
|
}
|
||||||
sep = ",";
|
sep = ",";
|
||||||
builder.addParameterRegistration( parameter.toJdbcParameterRegistration( i + offset, procedureCall ) );
|
builder.addParameterRegistration( registration );
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.append( ")}" );
|
buffer.append( ")}" );
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Queryable;
|
|
||||||
import org.hibernate.procedure.NoSuchParameterException;
|
import org.hibernate.procedure.NoSuchParameterException;
|
||||||
import org.hibernate.procedure.ParameterStrategyException;
|
import org.hibernate.procedure.ParameterStrategyException;
|
||||||
import org.hibernate.procedure.ProcedureCall;
|
import org.hibernate.procedure.ProcedureCall;
|
||||||
|
@ -591,7 +590,7 @@ public class ProcedureCallImpl<R>
|
||||||
|
|
||||||
final Map<ProcedureParameter<?>, JdbcCallParameterRegistration> parameterRegistrations = new IdentityHashMap<>();
|
final Map<ProcedureParameter<?>, JdbcCallParameterRegistration> parameterRegistrations = new IdentityHashMap<>();
|
||||||
final List<JdbcCallRefCursorExtractor> refCursorExtractors = new ArrayList<>();
|
final List<JdbcCallRefCursorExtractor> refCursorExtractors = new ArrayList<>();
|
||||||
if ( functionReturn != null ) {
|
if ( call.getFunctionReturn() != null ) {
|
||||||
parameterRegistrations.put( functionReturn, call.getFunctionReturn() );
|
parameterRegistrations.put( functionReturn, call.getFunctionReturn() );
|
||||||
final JdbcCallRefCursorExtractorImpl refCursorExtractor = call.getFunctionReturn().getRefCursorExtractor();
|
final JdbcCallRefCursorExtractorImpl refCursorExtractor = call.getFunctionReturn().getRefCursorExtractor();
|
||||||
if ( refCursorExtractor != null ) {
|
if ( refCursorExtractor != null ) {
|
||||||
|
@ -620,7 +619,6 @@ public class ProcedureCallImpl<R>
|
||||||
procedureName,
|
procedureName,
|
||||||
call,
|
call,
|
||||||
statement,
|
statement,
|
||||||
parameterMetadata.getParameterStrategy(),
|
|
||||||
parameterMetadata,
|
parameterMetadata,
|
||||||
getSession()
|
getSession()
|
||||||
);
|
);
|
||||||
|
@ -690,7 +688,7 @@ public class ProcedureCallImpl<R>
|
||||||
// Note that this should actually happen in an executor
|
// Note that this should actually happen in an executor
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int paramBindingPosition = functionReturn == null ? 1 : 2;
|
int paramBindingPosition = call.getFunctionReturn() == null ? 1 : 2;
|
||||||
for ( JdbcParameterBinder parameterBinder : call.getParameterBinders() ) {
|
for ( JdbcParameterBinder parameterBinder : call.getParameterBinders() ) {
|
||||||
parameterBinder.bindParameterValue(
|
parameterBinder.bindParameterValue(
|
||||||
statement,
|
statement,
|
||||||
|
|
|
@ -201,8 +201,8 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
|
||||||
.getJdbcSessionContext()
|
.getJdbcSessionContext()
|
||||||
.getServiceRegistry().getService( JdbcEnvironment.class )
|
.getServiceRegistry().getService( JdbcEnvironment.class )
|
||||||
.getExtractedDatabaseMetaData();
|
.getExtractedDatabaseMetaData();
|
||||||
return
|
return procedureCall.getFunctionReturn() == null
|
||||||
databaseMetaData.supportsNamedParameters()
|
&& databaseMetaData.supportsNamedParameters()
|
||||||
&& hibernateType instanceof ProcedureParameterNamedBinder
|
&& hibernateType instanceof ProcedureParameterNamedBinder
|
||||||
&& ( (ProcedureParameterNamedBinder<?>) hibernateType ).canDoSetting();
|
&& ( (ProcedureParameterNamedBinder<?>) hibernateType ).canDoSetting();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.procedure.spi.ProcedureParameterImplementor;
|
||||||
import org.hibernate.query.spi.ProcedureParameterMetadataImplementor;
|
import org.hibernate.query.spi.ProcedureParameterMetadataImplementor;
|
||||||
import org.hibernate.sql.exec.internal.JdbcCallImpl;
|
import org.hibernate.sql.exec.internal.JdbcCallImpl;
|
||||||
import org.hibernate.sql.exec.spi.JdbcCall;
|
import org.hibernate.sql.exec.spi.JdbcCall;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcCallParameterRegistration;
|
||||||
|
|
||||||
import jakarta.persistence.ParameterMode;
|
import jakarta.persistence.ParameterMode;
|
||||||
|
|
||||||
|
@ -38,9 +39,11 @@ public class StandardCallableStatementSupport extends AbstractStandardCallableSt
|
||||||
public static final StandardCallableStatementSupport REF_CURSOR_INSTANCE = new StandardCallableStatementSupport( true );
|
public static final StandardCallableStatementSupport REF_CURSOR_INSTANCE = new StandardCallableStatementSupport( true );
|
||||||
|
|
||||||
private final boolean supportsRefCursors;
|
private final boolean supportsRefCursors;
|
||||||
|
private final boolean implicitReturn;
|
||||||
|
|
||||||
public StandardCallableStatementSupport(boolean supportsRefCursors) {
|
public StandardCallableStatementSupport(boolean supportsRefCursors) {
|
||||||
this.supportsRefCursors = supportsRefCursors;
|
this.supportsRefCursors = supportsRefCursors;
|
||||||
|
this.implicitReturn = !supportsRefCursors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,14 +53,13 @@ public class StandardCallableStatementSupport extends AbstractStandardCallableSt
|
||||||
final ProcedureParameterMetadataImplementor parameterMetadata = procedureCall.getParameterMetadata();
|
final ProcedureParameterMetadataImplementor parameterMetadata = procedureCall.getParameterMetadata();
|
||||||
final SharedSessionContractImplementor session = procedureCall.getSession();
|
final SharedSessionContractImplementor session = procedureCall.getSession();
|
||||||
final List<? extends ProcedureParameterImplementor<?>> registrations = parameterMetadata.getRegistrationsAsList();
|
final List<? extends ProcedureParameterImplementor<?>> registrations = parameterMetadata.getRegistrationsAsList();
|
||||||
final JdbcCallImpl.Builder builder = new JdbcCallImpl.Builder(
|
final ParameterStrategy parameterStrategy = functionReturn == null && parameterMetadata.hasNamedParameters() ?
|
||||||
parameterMetadata.hasNamedParameters() ?
|
|
||||||
ParameterStrategy.NAMED :
|
ParameterStrategy.NAMED :
|
||||||
ParameterStrategy.POSITIONAL
|
ParameterStrategy.POSITIONAL;
|
||||||
);
|
final JdbcCallImpl.Builder builder = new JdbcCallImpl.Builder( parameterStrategy );
|
||||||
final StringBuilder buffer;
|
final StringBuilder buffer;
|
||||||
final int offset;
|
final int offset;
|
||||||
if ( functionReturn != null ) {
|
if ( functionReturn != null && !implicitReturn ) {
|
||||||
offset = 2;
|
offset = 2;
|
||||||
buffer = new StringBuilder( 11 + procedureName.length() + registrations.size() * 2 ).append( "{?=call " );
|
buffer = new StringBuilder( 11 + procedureName.length() + registrations.size() * 2 ).append( "{?=call " );
|
||||||
builder.setFunctionReturn( functionReturn.toJdbcFunctionReturn( session ) );
|
builder.setFunctionReturn( functionReturn.toJdbcFunctionReturn( session ) );
|
||||||
|
@ -75,9 +77,19 @@ public class StandardCallableStatementSupport extends AbstractStandardCallableSt
|
||||||
if ( parameter.getMode() == ParameterMode.REF_CURSOR ) {
|
if ( parameter.getMode() == ParameterMode.REF_CURSOR ) {
|
||||||
verifyRefCursorSupport( session.getJdbcServices().getJdbcEnvironment().getDialect() );
|
verifyRefCursorSupport( session.getJdbcServices().getJdbcEnvironment().getDialect() );
|
||||||
}
|
}
|
||||||
buffer.append( sep ).append( "?" );
|
buffer.append( sep );
|
||||||
|
final JdbcCallParameterRegistration registration = parameter.toJdbcParameterRegistration(
|
||||||
|
i + offset,
|
||||||
|
procedureCall
|
||||||
|
);
|
||||||
|
if ( registration.getName() != null ) {
|
||||||
|
buffer.append( ':' ).append( registration.getName() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer.append( "?" );
|
||||||
|
}
|
||||||
sep = ",";
|
sep = ",";
|
||||||
builder.addParameterRegistration( parameter.toJdbcParameterRegistration( i + offset, procedureCall ) );
|
builder.addParameterRegistration( registration );
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.append( ")}" );
|
buffer.append( ")}" );
|
||||||
|
|
|
@ -22,7 +22,6 @@ public interface CallableStatementSupport {
|
||||||
String procedureName,
|
String procedureName,
|
||||||
JdbcCall procedureCall,
|
JdbcCall procedureCall,
|
||||||
CallableStatement statement,
|
CallableStatement statement,
|
||||||
ParameterStrategy parameterStrategy,
|
|
||||||
ProcedureParameterMetadataImplementor parameterMetadata,
|
ProcedureParameterMetadataImplementor parameterMetadata,
|
||||||
SharedSessionContractImplementor session);
|
SharedSessionContractImplementor session);
|
||||||
}
|
}
|
||||||
|
|
|
@ -404,6 +404,8 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
|
||||||
|
|
||||||
NavigablePath getNavigablePath();
|
NavigablePath getNavigablePath();
|
||||||
|
|
||||||
|
LockMode getLockMode();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the lock mode for this return.
|
* Set the lock mode for this return.
|
||||||
*
|
*
|
||||||
|
|
|
@ -39,6 +39,14 @@ public class FetchMementoBasicStandard implements FetchMementoBasic {
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BasicValuedModelPart getFetchedAttribute() {
|
||||||
|
return fetchedAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnAlias() {
|
||||||
|
return columnAlias;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FetchBuilder resolve(
|
public FetchBuilder resolve(
|
||||||
Parent parent,
|
Parent parent,
|
||||||
|
|
|
@ -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.internal;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
|
import org.hibernate.query.named.FetchMemento;
|
||||||
|
import org.hibernate.query.results.FetchBuilder;
|
||||||
|
import org.hibernate.query.results.complete.CompleteFetchBuilderEmbeddableValuedModelPart;
|
||||||
|
import org.hibernate.query.spi.NavigablePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class FetchMementoEmbeddableStandard implements FetchMemento {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final EmbeddableValuedModelPart attributeMapping;
|
||||||
|
private final List<String> columnNames;
|
||||||
|
|
||||||
|
public FetchMementoEmbeddableStandard(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
EmbeddableValuedModelPart attributeMapping,
|
||||||
|
List<String> columnNames) {
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.attributeMapping = attributeMapping;
|
||||||
|
this.columnNames = columnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchBuilder resolve(
|
||||||
|
Parent parent,
|
||||||
|
Consumer<String> querySpaceConsumer,
|
||||||
|
ResultSetMappingResolutionContext context) {
|
||||||
|
return new CompleteFetchBuilderEmbeddableValuedModelPart( navigablePath, attributeMapping, columnNames );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbeddableValuedModelPart getAttributeMapping() {
|
||||||
|
return attributeMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getColumnNames() {
|
||||||
|
return columnNames;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,12 +6,16 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.query.internal;
|
package org.hibernate.query.internal;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
|
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||||
|
import org.hibernate.query.results.dynamic.DynamicResultBuilderEntityStandard;
|
||||||
import org.hibernate.query.spi.NavigablePath;
|
import org.hibernate.query.spi.NavigablePath;
|
||||||
import org.hibernate.query.named.FetchMemento;
|
import org.hibernate.query.named.FetchMemento;
|
||||||
import org.hibernate.query.results.FetchBuilder;
|
import org.hibernate.query.results.FetchBuilder;
|
||||||
|
@ -31,6 +35,7 @@ public class FetchMementoHbmStandard implements FetchMemento, FetchMemento.Paren
|
||||||
private final NavigablePath navigablePath;
|
private final NavigablePath navigablePath;
|
||||||
private final String ownerTableAlias;
|
private final String ownerTableAlias;
|
||||||
private final String tableAlias;
|
private final String tableAlias;
|
||||||
|
private final List<String> keyColumnNames;
|
||||||
private final LockMode lockMode;
|
private final LockMode lockMode;
|
||||||
private final FetchParentMemento parent;
|
private final FetchParentMemento parent;
|
||||||
private final Map<String, FetchMemento> fetchMementoMap;
|
private final Map<String, FetchMemento> fetchMementoMap;
|
||||||
|
@ -40,6 +45,7 @@ public class FetchMementoHbmStandard implements FetchMemento, FetchMemento.Paren
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
String ownerTableAlias,
|
String ownerTableAlias,
|
||||||
String tableAlias,
|
String tableAlias,
|
||||||
|
List<String> keyColumnNames,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
FetchParentMemento parent,
|
FetchParentMemento parent,
|
||||||
Map<String, FetchMemento> fetchMementoMap,
|
Map<String, FetchMemento> fetchMementoMap,
|
||||||
|
@ -47,6 +53,7 @@ public class FetchMementoHbmStandard implements FetchMemento, FetchMemento.Paren
|
||||||
this.navigablePath = navigablePath;
|
this.navigablePath = navigablePath;
|
||||||
this.ownerTableAlias = ownerTableAlias;
|
this.ownerTableAlias = ownerTableAlias;
|
||||||
this.tableAlias = tableAlias;
|
this.tableAlias = tableAlias;
|
||||||
|
this.keyColumnNames = keyColumnNames;
|
||||||
this.lockMode = lockMode;
|
this.lockMode = lockMode;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.fetchMementoMap = fetchMementoMap;
|
this.fetchMementoMap = fetchMementoMap;
|
||||||
|
@ -64,19 +71,34 @@ public class FetchMementoHbmStandard implements FetchMemento, FetchMemento.Paren
|
||||||
Consumer<String> querySpaceConsumer,
|
Consumer<String> querySpaceConsumer,
|
||||||
ResultSetMappingResolutionContext context) {
|
ResultSetMappingResolutionContext context) {
|
||||||
final Map<String, FetchBuilder> fetchBuilderMap = new HashMap<>();
|
final Map<String, FetchBuilder> fetchBuilderMap = new HashMap<>();
|
||||||
|
|
||||||
fetchMementoMap.forEach(
|
fetchMementoMap.forEach(
|
||||||
(attrName, fetchMemento) -> fetchBuilderMap.put(
|
(attrName, fetchMemento) -> fetchBuilderMap.put(
|
||||||
attrName,
|
attrName,
|
||||||
fetchMemento.resolve(this, querySpaceConsumer, context )
|
fetchMemento.resolve(this, querySpaceConsumer, context )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
final DynamicResultBuilderEntityStandard resultBuilder;
|
||||||
|
if ( fetchable instanceof PluralAttributeMapping ) {
|
||||||
|
resultBuilder = new DynamicResultBuilderEntityStandard(
|
||||||
|
(EntityMappingType) ( (PluralAttributeMapping) fetchable ).getElementDescriptor().getPartMappingType(),
|
||||||
|
tableAlias,
|
||||||
|
navigablePath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resultBuilder = new DynamicResultBuilderEntityStandard(
|
||||||
|
( (ToOneAttributeMapping) fetchable ).getEntityMappingType(),
|
||||||
|
tableAlias,
|
||||||
|
navigablePath
|
||||||
|
);
|
||||||
|
}
|
||||||
return new DynamicFetchBuilderLegacy(
|
return new DynamicFetchBuilderLegacy(
|
||||||
tableAlias,
|
tableAlias,
|
||||||
ownerTableAlias,
|
ownerTableAlias,
|
||||||
fetchable.getFetchableName(),
|
fetchable.getFetchableName(),
|
||||||
new ArrayList<>(),
|
keyColumnNames,
|
||||||
fetchBuilderMap
|
fetchBuilderMap,
|
||||||
|
resultBuilder
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.query.named;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
import org.hibernate.query.internal.ResultSetMappingResolutionContext;
|
||||||
import org.hibernate.query.named.FetchMemento;
|
|
||||||
import org.hibernate.query.results.FetchBuilder;
|
import org.hibernate.query.results.FetchBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* 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.complete;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import org.hibernate.engine.FetchTiming;
|
||||||
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
|
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||||
|
import org.hibernate.query.results.FetchBuilder;
|
||||||
|
import org.hibernate.query.results.ResultSetMappingSqlSelection;
|
||||||
|
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||||
|
import org.hibernate.query.spi.NavigablePath;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
|
import org.hibernate.sql.results.graph.Fetch;
|
||||||
|
import org.hibernate.sql.results.graph.FetchParent;
|
||||||
|
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
|
||||||
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
|
||||||
|
import static org.hibernate.query.results.ResultsHelper.impl;
|
||||||
|
import static org.hibernate.query.results.ResultsHelper.jdbcPositionToValuesArrayPosition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CompleteFetchBuilder for embeddable-valued ModelParts
|
||||||
|
*
|
||||||
|
* @author Christian Beikov
|
||||||
|
*/
|
||||||
|
public class CompleteFetchBuilderEmbeddableValuedModelPart
|
||||||
|
implements CompleteFetchBuilder, ModelPartReferenceEmbeddable {
|
||||||
|
private final NavigablePath navigablePath;
|
||||||
|
private final EmbeddableValuedModelPart modelPart;
|
||||||
|
private final List<String> columnAliases;
|
||||||
|
|
||||||
|
public CompleteFetchBuilderEmbeddableValuedModelPart(
|
||||||
|
NavigablePath navigablePath,
|
||||||
|
EmbeddableValuedModelPart modelPart,
|
||||||
|
List<String> columnAliases) {
|
||||||
|
this.navigablePath = navigablePath;
|
||||||
|
this.modelPart = modelPart;
|
||||||
|
this.columnAliases = columnAliases;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchBuilder cacheKeyInstance() {
|
||||||
|
return new CompleteFetchBuilderEmbeddableValuedModelPart(
|
||||||
|
navigablePath,
|
||||||
|
modelPart,
|
||||||
|
List.copyOf( columnAliases )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NavigablePath getNavigablePath() {
|
||||||
|
return navigablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddableValuedModelPart getReferencedPart() {
|
||||||
|
return modelPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fetch buildFetch(
|
||||||
|
FetchParent parent,
|
||||||
|
NavigablePath fetchPath,
|
||||||
|
JdbcValuesMetadata jdbcResultsMetadata,
|
||||||
|
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||||
|
DomainResultCreationState domainResultCreationState) {
|
||||||
|
assert fetchPath.equals( navigablePath );
|
||||||
|
final DomainResultCreationStateImpl creationStateImpl = impl( domainResultCreationState );
|
||||||
|
|
||||||
|
final TableGroup tableGroup = creationStateImpl.getFromClauseAccess().getTableGroup( navigablePath.getParent() );
|
||||||
|
modelPart.forEachSelectable(
|
||||||
|
(selectionIndex, selectableMapping) -> {
|
||||||
|
final TableReference tableReference = tableGroup.resolveTableReference( navigablePath, selectableMapping.getContainingTableExpression() );
|
||||||
|
final String mappedColumn = selectableMapping.getSelectionExpression();
|
||||||
|
final String columnAlias = columnAliases.get( selectionIndex );
|
||||||
|
creationStateImpl.resolveSqlSelection(
|
||||||
|
creationStateImpl.resolveSqlExpression(
|
||||||
|
SqlExpressionResolver.createColumnReferenceKey( tableReference, mappedColumn ),
|
||||||
|
processingState -> {
|
||||||
|
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
|
||||||
|
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||||
|
return new ResultSetMappingSqlSelection( valuesArrayPosition, selectableMapping.getJdbcMapping() );
|
||||||
|
}
|
||||||
|
),
|
||||||
|
modelPart.getJavaType(),
|
||||||
|
creationStateImpl.getSessionFactory().getTypeConfiguration()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return parent.generateFetchableFetch(
|
||||||
|
modelPart,
|
||||||
|
fetchPath,
|
||||||
|
FetchTiming.IMMEDIATE,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
domainResultCreationState
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final CompleteFetchBuilderEmbeddableValuedModelPart that = (CompleteFetchBuilderEmbeddableValuedModelPart) o;
|
||||||
|
return navigablePath.equals( that.navigablePath )
|
||||||
|
&& modelPart.equals( that.modelPart )
|
||||||
|
&& columnAliases.equals( that.columnAliases );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = navigablePath.hashCode();
|
||||||
|
result = 31 * result + modelPart.hashCode();
|
||||||
|
result = 31 * result + columnAliases.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ import org.hibernate.query.results.ResultBuilder;
|
||||||
import org.hibernate.query.results.ResultsHelper;
|
import org.hibernate.query.results.ResultsHelper;
|
||||||
import org.hibernate.query.results.ResultSetMappingSqlSelection;
|
import org.hibernate.query.results.ResultSetMappingSqlSelection;
|
||||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
|
@ -105,7 +106,9 @@ public class CompleteResultBuilderCollectionStandard implements CompleteResultBu
|
||||||
navigablePath,
|
navigablePath,
|
||||||
tableAlias,
|
tableAlias,
|
||||||
null,
|
null,
|
||||||
creationStateImpl,
|
new SqlAliasBaseConstant( tableAlias ),
|
||||||
|
creationStateImpl.getSqlExpressionResolver(),
|
||||||
|
creationStateImpl.getFromClauseAccess(),
|
||||||
sessionFactory
|
sessionFactory
|
||||||
);
|
);
|
||||||
fromClauseAccess.registerTableGroup( navigablePath, rootTableGroup );
|
fromClauseAccess.registerTableGroup( navigablePath, rootTableGroup );
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.query.results.FetchBuilder;
|
||||||
import org.hibernate.query.results.ResultBuilder;
|
import org.hibernate.query.results.ResultBuilder;
|
||||||
import org.hibernate.query.results.ResultsHelper;
|
import org.hibernate.query.results.ResultsHelper;
|
||||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||||
|
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||||
|
@ -82,6 +83,11 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
||||||
return entityDescriptor;
|
return entityDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LockMode getLockMode() {
|
||||||
|
return lockMode;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQuery.RootReturn setLockMode(LockMode lockMode) {
|
public NativeQuery.RootReturn setLockMode(LockMode lockMode) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
@ -131,9 +137,11 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
||||||
// since this is only used for result set mappings, the canUseInnerJoins value is irrelevant.
|
// since this is only used for result set mappings, the canUseInnerJoins value is irrelevant.
|
||||||
true,
|
true,
|
||||||
navigablePath,
|
navigablePath,
|
||||||
|
tableAlias,
|
||||||
null,
|
null,
|
||||||
null,
|
new SqlAliasBaseConstant( tableAlias ),
|
||||||
impl,
|
impl.getSqlExpressionResolver(),
|
||||||
|
impl.getFromClauseAccess(),
|
||||||
impl.getCreationContext()
|
impl.getCreationContext()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -141,7 +149,7 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
||||||
return new EntityResultImpl(
|
return new EntityResultImpl(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
entityDescriptor,
|
entityDescriptor,
|
||||||
null,
|
tableAlias,
|
||||||
lockMode,
|
lockMode,
|
||||||
(entityResult) -> {
|
(entityResult) -> {
|
||||||
if ( discriminatorFetchBuilder == null ) {
|
if ( discriminatorFetchBuilder == null ) {
|
||||||
|
|
|
@ -85,7 +85,6 @@ public abstract class AbstractFetchBuilderContainer<T extends AbstractFetchBuild
|
||||||
}
|
}
|
||||||
|
|
||||||
final DynamicFetchBuilderStandard fetchBuilder = new DynamicFetchBuilderStandard(
|
final DynamicFetchBuilderStandard fetchBuilder = new DynamicFetchBuilderStandard(
|
||||||
this,
|
|
||||||
propertyName
|
propertyName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
||||||
private final Map<String, FetchBuilder> fetchBuilderMap;
|
private final Map<String, FetchBuilder> fetchBuilderMap;
|
||||||
private final DynamicResultBuilderEntityStandard resultBuilderEntity;
|
private final DynamicResultBuilderEntityStandard resultBuilderEntity;
|
||||||
|
|
||||||
|
private LockMode lockMode;
|
||||||
|
|
||||||
public DynamicFetchBuilderLegacy(
|
public DynamicFetchBuilderLegacy(
|
||||||
String tableAlias,
|
String tableAlias,
|
||||||
String ownerTableAlias,
|
String ownerTableAlias,
|
||||||
|
@ -164,6 +166,7 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
||||||
keyDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();
|
keyDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !columnNames.isEmpty() ) {
|
||||||
keyDescriptor.forEachSelectable(
|
keyDescriptor.forEachSelectable(
|
||||||
(selectionIndex, selectableMapping) -> {
|
(selectionIndex, selectableMapping) -> {
|
||||||
resolveSqlSelection(
|
resolveSqlSelection(
|
||||||
|
@ -178,10 +181,10 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// We process the fetch builder such that it contains a resultBuilderEntity before calling this method in ResultSetMappingProcessor
|
// We process the fetch builder such that it contains a resultBuilderEntity before calling this method in ResultSetMappingProcessor
|
||||||
assert resultBuilderEntity != null;
|
if ( resultBuilderEntity != null ) {
|
||||||
|
|
||||||
return resultBuilderEntity.buildFetch(
|
return resultBuilderEntity.buildFetch(
|
||||||
parent,
|
parent,
|
||||||
attributeMapping,
|
attributeMapping,
|
||||||
|
@ -189,17 +192,16 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
||||||
creationState
|
creationState
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
return parent.generateFetchableFetch(
|
return parent.generateFetchableFetch(
|
||||||
attributeMapping,
|
attributeMapping,
|
||||||
fetchPath,
|
parent.resolveNavigablePath( attributeMapping ),
|
||||||
FetchTiming.IMMEDIATE,
|
FetchTiming.IMMEDIATE,
|
||||||
true,
|
true,
|
||||||
null,
|
null,
|
||||||
domainResultCreationState
|
domainResultCreationState
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void resolveSqlSelection(
|
private void resolveSqlSelection(
|
||||||
String columnAlias,
|
String columnAlias,
|
||||||
|
@ -235,17 +237,21 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQuery.FetchReturn setLockMode(LockMode lockMode) {
|
public NativeQuery.FetchReturn setLockMode(LockMode lockMode) {
|
||||||
return null;
|
this.lockMode = lockMode;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQuery.FetchReturn addProperty(String propertyName, String columnAlias) {
|
public NativeQuery.FetchReturn addProperty(String propertyName, String columnAlias) {
|
||||||
return null;
|
addProperty( propertyName ).addColumnAlias( columnAlias );
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQuery.ReturnProperty addProperty(String propertyName) {
|
public NativeQuery.ReturnProperty addProperty(String propertyName) {
|
||||||
return null;
|
DynamicFetchBuilderStandard fetchBuilder = new DynamicFetchBuilderStandard( propertyName );
|
||||||
|
fetchBuilderMap.put( propertyName, fetchBuilder );
|
||||||
|
return fetchBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
||||||
|
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||||
import org.hibernate.query.NativeQuery;
|
import org.hibernate.query.NativeQuery;
|
||||||
import org.hibernate.query.spi.NavigablePath;
|
import org.hibernate.query.spi.NavigablePath;
|
||||||
|
@ -38,24 +39,15 @@ import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnRefere
|
||||||
public class DynamicFetchBuilderStandard
|
public class DynamicFetchBuilderStandard
|
||||||
implements DynamicFetchBuilder, NativeQuery.ReturnProperty {
|
implements DynamicFetchBuilder, NativeQuery.ReturnProperty {
|
||||||
|
|
||||||
private final DynamicFetchBuilderContainer container;
|
|
||||||
private final String fetchableName;
|
private final String fetchableName;
|
||||||
|
|
||||||
private final List<String> columnNames;
|
private final List<String> columnNames;
|
||||||
|
|
||||||
public DynamicFetchBuilderStandard(
|
public DynamicFetchBuilderStandard(String fetchableName) {
|
||||||
DynamicFetchBuilderContainer container,
|
|
||||||
String fetchableName) {
|
|
||||||
this.container = container;
|
|
||||||
this.fetchableName = fetchableName;
|
this.fetchableName = fetchableName;
|
||||||
this.columnNames = new ArrayList<>();
|
this.columnNames = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DynamicFetchBuilderStandard(
|
private DynamicFetchBuilderStandard(String fetchableName, List<String> columnNames) {
|
||||||
DynamicFetchBuilderContainer container,
|
|
||||||
String fetchableName,
|
|
||||||
List<String> columnNames) {
|
|
||||||
this.container = container;
|
|
||||||
this.fetchableName = fetchableName;
|
this.fetchableName = fetchableName;
|
||||||
this.columnNames = columnNames;
|
this.columnNames = columnNames;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +55,6 @@ public class DynamicFetchBuilderStandard
|
||||||
@Override
|
@Override
|
||||||
public DynamicFetchBuilderStandard cacheKeyInstance() {
|
public DynamicFetchBuilderStandard cacheKeyInstance() {
|
||||||
return new DynamicFetchBuilderStandard(
|
return new DynamicFetchBuilderStandard(
|
||||||
container,
|
|
||||||
fetchableName,
|
fetchableName,
|
||||||
List.copyOf( columnNames )
|
List.copyOf( columnNames )
|
||||||
);
|
);
|
||||||
|
@ -71,7 +62,6 @@ public class DynamicFetchBuilderStandard
|
||||||
|
|
||||||
public DynamicFetchBuilderStandard cacheKeyInstance(DynamicFetchBuilderContainer container) {
|
public DynamicFetchBuilderStandard cacheKeyInstance(DynamicFetchBuilderContainer container) {
|
||||||
return new DynamicFetchBuilderStandard(
|
return new DynamicFetchBuilderStandard(
|
||||||
container,
|
|
||||||
fetchableName,
|
fetchableName,
|
||||||
List.copyOf( columnNames )
|
List.copyOf( columnNames )
|
||||||
);
|
);
|
||||||
|
@ -124,6 +114,17 @@ public class DynamicFetchBuilderStandard
|
||||||
creationStateImpl
|
creationStateImpl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else if ( attributeMapping instanceof EmbeddedAttributeMapping ) {
|
||||||
|
attributeMapping.forEachSelectable( selectableConsumer );
|
||||||
|
return parent.generateFetchableFetch(
|
||||||
|
attributeMapping,
|
||||||
|
fetchPath,
|
||||||
|
FetchTiming.IMMEDIATE,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
creationStateImpl
|
||||||
|
);
|
||||||
|
}
|
||||||
else if ( attributeMapping instanceof ToOneAttributeMapping ) {
|
else if ( attributeMapping instanceof ToOneAttributeMapping ) {
|
||||||
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
|
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
|
||||||
toOneAttributeMapping.getForeignKeyDescriptor().visitKeySelectables( selectableConsumer );
|
toOneAttributeMapping.getForeignKeyDescriptor().visitKeySelectables( selectableConsumer );
|
||||||
|
|
|
@ -69,6 +69,11 @@ public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilde
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LockMode getLockMode() {
|
||||||
|
return explicitLockMode;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQuery.RootReturn setLockMode(LockMode lockMode) {
|
public NativeQuery.RootReturn setLockMode(LockMode lockMode) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -103,6 +103,11 @@ public class DynamicResultBuilderEntityStandard
|
||||||
return navigablePath;
|
return navigablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LockMode getLockMode() {
|
||||||
|
return lockMode;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NativeQuery.RootReturn addIdColumnAliases(String... aliases) {
|
public NativeQuery.RootReturn addIdColumnAliases(String... aliases) {
|
||||||
if ( idColumnNames == null ) {
|
if ( idColumnNames == null ) {
|
||||||
|
@ -153,7 +158,7 @@ public class DynamicResultBuilderEntityStandard
|
||||||
return buildResultOrFetch(
|
return buildResultOrFetch(
|
||||||
(tableGroup) -> parent.generateFetchableFetch(
|
(tableGroup) -> parent.generateFetchableFetch(
|
||||||
fetchable,
|
fetchable,
|
||||||
navigablePath,
|
parent.resolveNavigablePath( fetchable ),
|
||||||
FetchTiming.IMMEDIATE,
|
FetchTiming.IMMEDIATE,
|
||||||
true,
|
true,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -173,16 +173,17 @@ public class ParameterParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkIsNotAFunctionCall(String sqlString) {
|
private static void checkIsNotAFunctionCall(String sqlString) {
|
||||||
if ( !( sqlString.startsWith( "{" ) && sqlString.endsWith( "}" ) ) ) {
|
final String trimmed = sqlString.trim();
|
||||||
|
if ( !( trimmed.startsWith( "{" ) && trimmed.endsWith( "}" ) ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int chopLocation = sqlString.indexOf( "call" );
|
final int chopLocation = trimmed.indexOf( "call" );
|
||||||
if ( chopLocation <= 0 ) {
|
if ( chopLocation <= 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String checkString = sqlString.substring( 1, chopLocation + 4 );
|
final String checkString = trimmed.substring( 1, chopLocation + 4 );
|
||||||
final String fixture = "?=call";
|
final String fixture = "?=call";
|
||||||
int fixturePosition = 0;
|
int fixturePosition = 0;
|
||||||
boolean matches = true;
|
boolean matches = true;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.engine.query.ParameterRecognitionException;
|
||||||
import org.hibernate.query.internal.QueryParameterNamedImpl;
|
import org.hibernate.query.internal.QueryParameterNamedImpl;
|
||||||
import org.hibernate.query.internal.QueryParameterPositionalImpl;
|
import org.hibernate.query.internal.QueryParameterPositionalImpl;
|
||||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||||
|
@ -125,7 +126,7 @@ public class ParameterRecognizerImpl implements ParameterRecognizer {
|
||||||
parameterStyle = ParameterStyle.NAMED;
|
parameterStyle = ParameterStyle.NAMED;
|
||||||
}
|
}
|
||||||
else if ( parameterStyle != ParameterStyle.NAMED ) {
|
else if ( parameterStyle != ParameterStyle.NAMED ) {
|
||||||
throw new IllegalStateException( "Cannot mix parameter styles between JDBC-style, ordinal and named in the same query" );
|
throw new ParameterRecognitionException( "Cannot mix parameter styles between JDBC-style, ordinal and named in the same query" );
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryParameterImplementor<?> parameter = null;
|
QueryParameterImplementor<?> parameter = null;
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
|
@ -233,6 +234,7 @@ public class ResultSetMappingProcessor implements SQLQueryParser.ParserContext {
|
||||||
alias2Persister.get( fetchBuilder.getTableAlias() ).findContainingEntityMapping(),
|
alias2Persister.get( fetchBuilder.getTableAlias() ).findContainingEntityMapping(),
|
||||||
fetchBuilder.getTableAlias(),
|
fetchBuilder.getTableAlias(),
|
||||||
suffix,
|
suffix,
|
||||||
|
null,
|
||||||
determineNavigablePath( fetchBuilder )
|
determineNavigablePath( fetchBuilder )
|
||||||
);
|
);
|
||||||
final SQLLoadable loadable = (SQLLoadable) alias2Persister.get( fetchBuilder.getOwnerAlias() );
|
final SQLLoadable loadable = (SQLLoadable) alias2Persister.get( fetchBuilder.getOwnerAlias() );
|
||||||
|
@ -296,6 +298,7 @@ public class ResultSetMappingProcessor implements SQLQueryParser.ParserContext {
|
||||||
rootReturn.getEntityMapping(),
|
rootReturn.getEntityMapping(),
|
||||||
rootReturn.getTableAlias(),
|
rootReturn.getTableAlias(),
|
||||||
suffix,
|
suffix,
|
||||||
|
rootReturn.getLockMode(),
|
||||||
new NavigablePath( rootReturn.getEntityMapping().getEntityName() )
|
new NavigablePath( rootReturn.getEntityMapping().getEntityName() )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -304,6 +307,7 @@ public class ResultSetMappingProcessor implements SQLQueryParser.ParserContext {
|
||||||
EntityMappingType entityMapping,
|
EntityMappingType entityMapping,
|
||||||
String tableAlias,
|
String tableAlias,
|
||||||
String suffix,
|
String suffix,
|
||||||
|
LockMode lockMode,
|
||||||
NavigablePath navigablePath) {
|
NavigablePath navigablePath) {
|
||||||
final SQLLoadable loadable = (SQLLoadable) entityMapping.getEntityPersister();
|
final SQLLoadable loadable = (SQLLoadable) entityMapping.getEntityPersister();
|
||||||
final DynamicResultBuilderEntityStandard resultBuilderEntity = new DynamicResultBuilderEntityStandard(
|
final DynamicResultBuilderEntityStandard resultBuilderEntity = new DynamicResultBuilderEntityStandard(
|
||||||
|
@ -311,6 +315,7 @@ public class ResultSetMappingProcessor implements SQLQueryParser.ParserContext {
|
||||||
tableAlias,
|
tableAlias,
|
||||||
navigablePath
|
navigablePath
|
||||||
);
|
);
|
||||||
|
resultBuilderEntity.setLockMode( lockMode );
|
||||||
|
|
||||||
final String[] identifierAliases = loadable.getIdentifierAliases( suffix );
|
final String[] identifierAliases = loadable.getIdentifierAliases( suffix );
|
||||||
resultBuilderEntity.addIdColumnAliases( identifierAliases );
|
resultBuilderEntity.addIdColumnAliases( identifierAliases );
|
||||||
|
|
|
@ -49,6 +49,11 @@ public class JdbcCallParameterRegistrationImpl implements JdbcCallParameterRegis
|
||||||
this.refCursorExtractor = refCursorExtractor;
|
this.refCursorExtractor = refCursorExtractor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcParameterBinder getParameterBinder() {
|
public JdbcParameterBinder getParameterBinder() {
|
||||||
return parameterBinder;
|
return parameterBinder;
|
||||||
|
|
|
@ -18,6 +18,9 @@ import org.hibernate.sql.exec.internal.JdbcCallRefCursorExtractorImpl;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface JdbcCallParameterRegistration {
|
public interface JdbcCallParameterRegistration {
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
|
||||||
ParameterMode getParameterMode();
|
ParameterMode getParameterMode();
|
||||||
|
|
||||||
void registerParameter(
|
void registerParameter(
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.query.ResultListTransformer;
|
||||||
import org.hibernate.sql.results.jdbc.spi.JdbcValues;
|
import org.hibernate.sql.results.jdbc.spi.JdbcValues;
|
||||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
@ -124,6 +125,13 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
|
||||||
persistenceContext.getLoadContexts().deregister( jdbcValuesSourceProcessingState );
|
persistenceContext.getLoadContexts().deregister( jdbcValuesSourceProcessingState );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
final ResultListTransformer<R> resultListTransformer = (ResultListTransformer<R>) jdbcValuesSourceProcessingState.getExecutionContext()
|
||||||
|
.getQueryOptions()
|
||||||
|
.getResultListTransformer();
|
||||||
|
if ( resultListTransformer != null ) {
|
||||||
|
return resultListTransformer.transformList( results );
|
||||||
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
catch (RuntimeException e) {
|
catch (RuntimeException e) {
|
||||||
|
|
|
@ -1,87 +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.orm.test.annotations.entity;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Types;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.usertype.UserType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to persist and retrieve objects of type 'PhoneNumber'
|
|
||||||
*
|
|
||||||
* @author Sharath Reddy
|
|
||||||
*/
|
|
||||||
public class PhoneNumberType implements UserType {
|
|
||||||
|
|
||||||
public int[] sqlTypes() {
|
|
||||||
return new int[]{Types.VARCHAR};
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> returnedClass() {
|
|
||||||
return PhoneNumber.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object x, Object y) throws HibernateException {
|
|
||||||
return ( x == y ) || ( x != null && x.equals( y ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode(Object x) throws HibernateException {
|
|
||||||
return x.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
|
|
||||||
String result = rs.getString( position );
|
|
||||||
if ( rs.wasNull() ) return null;
|
|
||||||
|
|
||||||
if (result.length() <= 6) {
|
|
||||||
return new PhoneNumber(result);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return new OverseasPhoneNumber(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
|
|
||||||
if ( value == null ) {
|
|
||||||
st.setNull( index, sqlTypes()[0] );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhoneNumber phoneNumber = (PhoneNumber) value;
|
|
||||||
String number = phoneNumber.getNumber();
|
|
||||||
st.setString( index, number);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object deepCopy(Object value) throws HibernateException {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMutable() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Serializable disassemble(Object value) throws HibernateException {
|
|
||||||
return (Serializable) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object assemble(Serializable cached, Object owner) throws HibernateException {
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object replace(Object original, Object target, Object owner) throws HibernateException {
|
|
||||||
return original;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -44,7 +44,6 @@ import static org.hibernate.jpa.HibernateHints.HINT_CALLABLE_FUNCTION;
|
||||||
@NamedNativeQuery(
|
@NamedNativeQuery(
|
||||||
name = "fn_person_and_phones_hana",
|
name = "fn_person_and_phones_hana",
|
||||||
query = "select \"pr.id\", \"pr.name\", \"pr.nickName\", \"pr.address\", \"pr.createdOn\", \"pr.version\", \"ph.id\", \"ph.person_id\", \"ph.phone_number\", \"ph.valid\" from fn_person_and_phones( ? )",
|
query = "select \"pr.id\", \"pr.name\", \"pr.nickName\", \"pr.address\", \"pr.createdOn\", \"pr.version\", \"ph.id\", \"ph.person_id\", \"ph.phone_number\", \"ph.valid\" from fn_person_and_phones( ? )",
|
||||||
callable = false,
|
|
||||||
resultSetMapping = "person_with_phones_hana"
|
resultSetMapping = "person_with_phones_hana"
|
||||||
)
|
)
|
||||||
@SqlResultSetMappings({
|
@SqlResultSetMappings({
|
||||||
|
|
Loading…
Reference in New Issue