Fixes for the move of jpa.test.query to orm.test
* Allow JdbcTypeDescriptor to resolve JavaTypeDescriptor also based on precision/scale to support resolving VARCHAR(1) to Character * Implement support for rendering comments and hints for DML statements. * Implement support for tuple transformer * Apply type inference on SQM parameters and put coercion behind `isLoadByIdComplianceEnabled` consistently * Implement native query result type validation * Fix some temporal type related resolving issues * Fix parameter validation issue * Apply delayed fetch builders for implicit basic attributes for result set mappings * Use resolved JdbcTypeDescriptor and column length/scale to resolve recommended JdbcTypeDescriptor * Fix type resolving for composite path sources * Make ManagedDomainType implement AllowableParameterType * Make DiscriminatorSqmPathSource implement AllowableParameterType * Fix some id-class related path source issues
This commit is contained in:
parent
d4ecfbc1b8
commit
f1680fabcd
|
@ -15,6 +15,7 @@ import jakarta.persistence.TemporalType;
|
|||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
|
@ -187,7 +188,28 @@ public class InferredBasicValueResolver {
|
|||
if ( explicitJdbcType != null ) {
|
||||
// we have an explicit STD, but no JTD - infer JTD
|
||||
// - NOTE : yes its an odd case, but its easy to implement here, so...
|
||||
final BasicJavaDescriptor recommendedJtd = explicitJdbcType.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
Integer length = null;
|
||||
Integer scale = null;
|
||||
if ( selectable instanceof Column ) {
|
||||
final Column column = (Column) selectable;
|
||||
if ( column.getPrecision() != null && column.getPrecision() > 0 ) {
|
||||
length = column.getPrecision();
|
||||
scale = column.getScale();
|
||||
}
|
||||
else if ( column.getLength() != null ) {
|
||||
if ( column.getLength() > (long) Integer.MAX_VALUE ) {
|
||||
length = Integer.MAX_VALUE;
|
||||
}
|
||||
else {
|
||||
length = column.getLength().intValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
final BasicJavaDescriptor recommendedJtd = explicitJdbcType.getJdbcRecommendedJavaTypeMapping(
|
||||
length,
|
||||
scale,
|
||||
typeConfiguration
|
||||
);
|
||||
final BasicType<?> resolved = typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
recommendedJtd,
|
||||
explicitJdbcType
|
||||
|
@ -460,7 +482,10 @@ public class InferredBasicValueResolver {
|
|||
);
|
||||
}
|
||||
else {
|
||||
basicType = registeredType;
|
||||
basicType = (BasicType) legacyTemporalType.resolveTemporalPrecision(
|
||||
reflectedJtd.getPrecision(),
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
|
||||
return new InferredBasicValueResolution(
|
||||
|
|
|
@ -37,7 +37,6 @@ public class NativeQueryInterpreterStandardImpl implements NativeQueryInterprete
|
|||
queryDefinition.getAffectedTableNames(),
|
||||
queryDefinition.getQueryParameterList(),
|
||||
queryDefinition.getResultSetMapping(),
|
||||
queryDefinition.getRowTransformer(),
|
||||
sessionFactory
|
||||
);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ public interface NativeQueryInterpreter extends Service {
|
|||
queryDefinition.getAffectedTableNames(),
|
||||
queryDefinition.getQueryParameterList(),
|
||||
queryDefinition.getResultSetMapping(),
|
||||
queryDefinition.getRowTransformer(),
|
||||
sessionFactory
|
||||
);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import java.util.TimeZone;
|
|||
import java.util.UUID;
|
||||
import jakarta.persistence.FlushModeType;
|
||||
import jakarta.persistence.TransactionRequiredException;
|
||||
import jakarta.persistence.Tuple;
|
||||
import jakarta.persistence.criteria.CriteriaDelete;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.CriteriaUpdate;
|
||||
|
@ -52,6 +53,7 @@ import org.hibernate.jdbc.ReturningWork;
|
|||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.jdbc.WorkExecutorVisitable;
|
||||
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
|
||||
import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.internal.ProcedureCallImpl;
|
||||
|
@ -704,7 +706,12 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
|
||||
try {
|
||||
NativeQueryImplementor query = createNativeQuery( sqlString );
|
||||
query.addEntity( "alias1", resultClass.getName(), LockMode.READ );
|
||||
if ( Tuple.class.equals( resultClass ) ) {
|
||||
query.setTupleTransformer( new NativeQueryTupleTransformer() );
|
||||
}
|
||||
else {
|
||||
query.addEntity( "alias1", resultClass.getName(), LockMode.READ );
|
||||
}
|
||||
return query;
|
||||
}
|
||||
catch (RuntimeException he) {
|
||||
|
@ -740,7 +747,6 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
}
|
||||
|
||||
return query;
|
||||
// throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -124,8 +124,15 @@ public class MultiIdLoaderStandard<T> implements MultiIdEntityLoader<T> {
|
|||
final List<Object> idsInBatch = new ArrayList<>();
|
||||
final List<Integer> elementPositionsLoadedByBatch = new ArrayList<>();
|
||||
|
||||
final boolean coerce = !sessionFactory.getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled();
|
||||
for ( int i = 0; i < ids.length; i++ ) {
|
||||
final Object id = entityDescriptor.getIdentifierMapping().getJavaTypeDescriptor().coerce( ids[i], session );
|
||||
final Object id;
|
||||
if ( coerce ) {
|
||||
id = entityDescriptor.getIdentifierMapping().getJavaTypeDescriptor().coerce( ids[i], session );
|
||||
}
|
||||
else {
|
||||
id = ids[i];
|
||||
}
|
||||
final EntityKey entityKey = new EntityKey( id, entityDescriptor );
|
||||
|
||||
if ( loadOptions.isSessionCheckingEnabled() || loadOptions.isSecondLevelCacheCheckingEnabled() ) {
|
||||
|
@ -357,8 +364,15 @@ public class MultiIdLoaderStandard<T> implements MultiIdEntityLoader<T> {
|
|||
boolean foundAnyManagedEntities = false;
|
||||
final List<Object> nonManagedIds = new ArrayList<>();
|
||||
|
||||
final boolean coerce = !sessionFactory.getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled();
|
||||
for ( int i = 0; i < ids.length; i++ ) {
|
||||
final Object id = entityDescriptor.getIdentifierMapping().getJavaTypeDescriptor().coerce( ids[ i ], session );
|
||||
final Object id;
|
||||
if ( coerce ) {
|
||||
id = entityDescriptor.getIdentifierMapping().getJavaTypeDescriptor().coerce( ids[i], session );
|
||||
}
|
||||
else {
|
||||
id = ids[i];
|
||||
}
|
||||
final EntityKey entityKey = new EntityKey( id, entityDescriptor );
|
||||
|
||||
LoadEvent loadEvent = new LoadEvent(
|
||||
|
|
|
@ -410,17 +410,21 @@ public class MetadataContext {
|
|||
}
|
||||
}
|
||||
|
||||
( ( AttributeContainer) identifiableType ).getInFlightAccess().applyNonAggregatedIdAttributes( idAttributes );
|
||||
|
||||
// see if it also has an IdClass (identifier-mapper)
|
||||
final Component idClass = persistentClass.getIdentifierMapper();
|
||||
final EmbeddableTypeImpl<?> idClassType;
|
||||
if ( idClass != null ) {
|
||||
applyIdClassMetadata( (Component) persistentClass.getIdentifier(), idClass );
|
||||
idClassType = applyIdClassMetadata( (Component) persistentClass.getIdentifier(), idClass );
|
||||
}
|
||||
else {
|
||||
idClassType = null;
|
||||
}
|
||||
|
||||
( ( AttributeContainer) identifiableType ).getInFlightAccess().applyNonAggregatedIdAttributes( idAttributes, idClassType );
|
||||
}
|
||||
}
|
||||
|
||||
private void applyIdClassMetadata(Component identifier, Component idClass) {
|
||||
private EmbeddableTypeImpl<?> applyIdClassMetadata(Component identifier, Component idClass) {
|
||||
final JavaTypeDescriptorRegistry registry = getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry();
|
||||
final Class<?> componentClass = identifier.getComponentClass();
|
||||
|
@ -439,6 +443,7 @@ public class MetadataContext {
|
|||
getJpaMetamodel()
|
||||
);
|
||||
registerEmbeddableType( embeddableType, idClass );
|
||||
return embeddableType;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
|
|
|
@ -144,20 +144,26 @@ public class SimpleNaturalIdMapping extends AbstractNaturalIdMapping implements
|
|||
|
||||
@SuppressWarnings( "rawtypes" )
|
||||
public Object normalizeIncomingValue(Object naturalIdToLoad) {
|
||||
final Object normalizedValue;
|
||||
if ( naturalIdToLoad instanceof Map ) {
|
||||
final Map valueMap = (Map) naturalIdToLoad;
|
||||
assert valueMap.size() == 1;
|
||||
assert valueMap.containsKey( getAttribute().getAttributeName() );
|
||||
return getJavaTypeDescriptor().coerce( valueMap.get( getAttribute().getAttributeName() ), this );
|
||||
normalizedValue = valueMap.get( getAttribute().getAttributeName() );
|
||||
}
|
||||
|
||||
if ( naturalIdToLoad instanceof Object[] ) {
|
||||
else if ( naturalIdToLoad instanceof Object[] ) {
|
||||
final Object[] values = (Object[]) naturalIdToLoad;
|
||||
assert values.length == 1;
|
||||
return getJavaTypeDescriptor().coerce( values[0], this );
|
||||
normalizedValue = values[0];
|
||||
}
|
||||
else {
|
||||
normalizedValue = naturalIdToLoad;
|
||||
}
|
||||
|
||||
return getJavaTypeDescriptor().coerce( naturalIdToLoad, this );
|
||||
if ( getTypeConfiguration().getSessionFactory().getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled() ) {
|
||||
return normalizedValue;
|
||||
}
|
||||
return getJavaTypeDescriptor().coerce( normalizedValue, this );
|
||||
}
|
||||
|
||||
public SingularAttributeMapping getAttribute() {
|
||||
|
|
|
@ -45,8 +45,9 @@ public abstract class AbstractIdentifiableType<J>
|
|||
|
||||
private SingularPersistentAttribute<J,?> id;
|
||||
private Set<SingularPersistentAttribute<? super J,?>> nonAggregatedIdAttributes;
|
||||
private EmbeddableDomainType<?> idClassType;
|
||||
|
||||
private SqmPathSource identifierDescriptor;
|
||||
private SqmPathSource<?> identifierDescriptor;
|
||||
|
||||
|
||||
private final boolean isVersioned;
|
||||
|
@ -67,19 +68,17 @@ public abstract class AbstractIdentifiableType<J>
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected InFlightAccessImpl createInFlightAccess() {
|
||||
return new InFlightAccessImpl( super.createInFlightAccess() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public InFlightAccessImpl getInFlightAccess() {
|
||||
return (InFlightAccessImpl) super.getInFlightAccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource getIdentifierDescriptor() {
|
||||
public SqmPathSource<?> getIdentifierDescriptor() {
|
||||
return identifierDescriptor;
|
||||
}
|
||||
|
||||
|
@ -96,7 +95,7 @@ public abstract class AbstractIdentifiableType<J>
|
|||
@SuppressWarnings("unchecked")
|
||||
public IdentifiableDomainType<? super J> getSuperType() {
|
||||
// overridden simply to perform the cast
|
||||
return (IdentifiableDomainType) super.getSuperType();
|
||||
return (IdentifiableDomainType<? super J>) super.getSuperType();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -108,11 +107,11 @@ public abstract class AbstractIdentifiableType<J>
|
|||
@SuppressWarnings({ "unchecked" })
|
||||
public <Y> SingularPersistentAttribute<? super J, Y> getId(Class<Y> javaType) {
|
||||
ensureNoIdClass();
|
||||
SingularPersistentAttribute id = findIdAttribute();
|
||||
SingularPersistentAttribute<J, ?> id = findIdAttribute();
|
||||
if ( id != null ) {
|
||||
checkType( id, javaType );
|
||||
}
|
||||
return (SingularPersistentAttribute) id;
|
||||
return (SingularPersistentAttribute<? super J, Y>) id;
|
||||
}
|
||||
|
||||
private void ensureNoIdClass() {
|
||||
|
@ -125,16 +124,16 @@ public abstract class AbstractIdentifiableType<J>
|
|||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "RedundantIfStatement"})
|
||||
public SingularPersistentAttribute findIdAttribute() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public SingularPersistentAttribute<J, ?> findIdAttribute() {
|
||||
if ( id != null ) {
|
||||
return id;
|
||||
}
|
||||
else {
|
||||
if ( getSuperType() != null ) {
|
||||
SingularPersistentAttribute id = getSuperType().findIdAttribute();
|
||||
SingularPersistentAttribute<? super J, ?> id = getSuperType().findIdAttribute();
|
||||
if ( id != null ) {
|
||||
return id;
|
||||
return (SingularPersistentAttribute<J, ?>) id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,8 +141,7 @@ public abstract class AbstractIdentifiableType<J>
|
|||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void checkType(SingularPersistentAttribute attribute, Class javaType) {
|
||||
private void checkType(SingularPersistentAttribute<?, ?> attribute, Class<?> javaType) {
|
||||
if ( ! javaType.isAssignableFrom( attribute.getType().getJavaType() ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
|
@ -170,9 +168,9 @@ public abstract class AbstractIdentifiableType<J>
|
|||
|
||||
@Override
|
||||
public SimpleDomainType<?> getIdType() {
|
||||
final SingularPersistentAttribute id = findIdAttribute();
|
||||
final SingularPersistentAttribute<J, ?> id = findIdAttribute();
|
||||
if ( id != null ) {
|
||||
return (SimpleDomainType<?>) id.getType();
|
||||
return id.getType();
|
||||
}
|
||||
|
||||
Set<SingularPersistentAttribute<? super J, ?>> idClassAttributes = getIdClassAttributesSafely();
|
||||
|
@ -205,20 +203,19 @@ public abstract class AbstractIdentifiableType<J>
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<SingularAttribute<? super J, ?>> getIdClassAttributes() {
|
||||
if ( !hasIdClass() ) {
|
||||
throw new IllegalArgumentException( "This class [" + getJavaType() + "] does not define an IdClass" );
|
||||
}
|
||||
|
||||
final Set<SingularPersistentAttribute<? super J,?>> attributes = new HashSet<>();
|
||||
final Set<SingularAttribute<? super J, ?>> attributes = new HashSet<>();
|
||||
visitIdClassAttributes( attributes::add );
|
||||
|
||||
if ( attributes.isEmpty() ) {
|
||||
throw new IllegalArgumentException( "Unable to locate IdClass attributes [" + getJavaType() + "]" );
|
||||
}
|
||||
|
||||
return (Set) attributes;
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -228,6 +225,7 @@ public abstract class AbstractIdentifiableType<J>
|
|||
nonAggregatedIdAttributes.forEach( attributeConsumer );
|
||||
}
|
||||
else if ( getSuperType() != null ) {
|
||||
//noinspection rawtypes
|
||||
getSuperType().visitIdClassAttributes( (Consumer) attributeConsumer );
|
||||
}
|
||||
}
|
||||
|
@ -242,28 +240,28 @@ public abstract class AbstractIdentifiableType<J>
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@SuppressWarnings("unchecked")
|
||||
public <Y> SingularPersistentAttribute<? super J, Y> getVersion(Class<Y> javaType) {
|
||||
if ( ! hasVersionAttribute() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SingularPersistentAttribute version = findVersionAttribute();
|
||||
SingularPersistentAttribute<J, ?> version = findVersionAttribute();
|
||||
if ( version != null ) {
|
||||
checkType( version, javaType );
|
||||
}
|
||||
return (SingularPersistentAttribute) version;
|
||||
return (SingularPersistentAttribute<? super J, Y>) version;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SingularPersistentAttribute findVersionAttribute() {
|
||||
public SingularPersistentAttribute<J, ?> findVersionAttribute() {
|
||||
if ( versionAttribute != null ) {
|
||||
return versionAttribute;
|
||||
}
|
||||
|
||||
if ( getSuperType() != null ) {
|
||||
return getSuperType().findVersionAttribute();
|
||||
return (SingularPersistentAttribute<J, ?>) getSuperType().findVersionAttribute();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -308,22 +306,24 @@ public abstract class AbstractIdentifiableType<J>
|
|||
return versionAttribute;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private class InFlightAccessImpl extends AbstractManagedType.InFlightAccessImpl {
|
||||
private final InFlightAccess managedTypeAccess;
|
||||
private class InFlightAccessImpl extends AbstractManagedType<J>.InFlightAccessImpl {
|
||||
private final InFlightAccess<J> managedTypeAccess;
|
||||
|
||||
private InFlightAccessImpl(InFlightAccess managedTypeAccess) {
|
||||
private InFlightAccessImpl(InFlightAccess<J> managedTypeAccess) {
|
||||
this.managedTypeAccess = managedTypeAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyIdAttribute(SingularPersistentAttribute idAttribute) {
|
||||
public void applyIdAttribute(SingularPersistentAttribute<J, ?> idAttribute) {
|
||||
AbstractIdentifiableType.this.id = idAttribute;
|
||||
managedTypeAccess.addAttribute( idAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyNonAggregatedIdAttributes(Set idAttributes) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void applyNonAggregatedIdAttributes(
|
||||
Set<SingularPersistentAttribute<? super J, ?>> idAttributes,
|
||||
EmbeddableDomainType<?> idClassType) {
|
||||
if ( AbstractIdentifiableType.this.id != null ) {
|
||||
throw new IllegalArgumentException( "`AbstractIdentifiableType#id` already set on call to `#applyNonAggregatedIdAttribute`" );
|
||||
}
|
||||
|
@ -336,31 +336,30 @@ public abstract class AbstractIdentifiableType<J>
|
|||
AbstractIdentifiableType.this.nonAggregatedIdAttributes = Collections.EMPTY_SET;
|
||||
}
|
||||
else {
|
||||
for ( SingularPersistentAttribute idAttribute : (Set<SingularPersistentAttribute>) idAttributes ) {
|
||||
for ( SingularPersistentAttribute<? super J, ?> idAttribute : idAttributes ) {
|
||||
if ( AbstractIdentifiableType.this == idAttribute.getDeclaringType() ) {
|
||||
addAttribute( idAttribute );
|
||||
addAttribute( (PersistentAttribute<J, ?>) idAttribute );
|
||||
}
|
||||
}
|
||||
|
||||
AbstractIdentifiableType.this.nonAggregatedIdAttributes = (Set) idAttributes;
|
||||
AbstractIdentifiableType.this.nonAggregatedIdAttributes = idAttributes;
|
||||
}
|
||||
AbstractIdentifiableType.this.idClassType = idClassType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyIdClassAttributes(Set idClassAttributes) {
|
||||
applyNonAggregatedIdAttributes( idClassAttributes );
|
||||
public void applyIdClassAttributes(Set<SingularPersistentAttribute<? super J, ?>> idClassAttributes) {
|
||||
applyNonAggregatedIdAttributes( idClassAttributes, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void applyVersionAttribute(SingularPersistentAttribute versionAttribute) {
|
||||
public void applyVersionAttribute(SingularPersistentAttribute<J, ?> versionAttribute) {
|
||||
AbstractIdentifiableType.this.versionAttribute = versionAttribute;
|
||||
managedTypeAccess.addAttribute( versionAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addAttribute(PersistentAttribute attribute) {
|
||||
public void addAttribute(PersistentAttribute<J, ?> attribute) {
|
||||
managedTypeAccess.addAttribute( attribute );
|
||||
}
|
||||
|
||||
|
@ -374,7 +373,7 @@ public abstract class AbstractIdentifiableType<J>
|
|||
|
||||
private static final Logger log = Logger.getLogger( AbstractIdentifiableType.class );
|
||||
|
||||
private SqmPathSource interpretIdDescriptor() {
|
||||
private SqmPathSource<?> interpretIdDescriptor() {
|
||||
log.tracef( "Interpreting domain-model identifier descriptor" );
|
||||
|
||||
if ( getSuperType() != null ) {
|
||||
|
@ -384,18 +383,16 @@ public abstract class AbstractIdentifiableType<J>
|
|||
// simple id or aggregate composite id
|
||||
final SimpleDomainType<?> type = id.getType();
|
||||
if ( type instanceof BasicDomainType ) {
|
||||
//noinspection unchecked
|
||||
return new BasicSqmPathSource(
|
||||
return new BasicSqmPathSource<>(
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||
(BasicDomainType) type,
|
||||
(BasicDomainType<?>) type,
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE
|
||||
);
|
||||
}
|
||||
else {
|
||||
assert type instanceof EmbeddableDomainType;
|
||||
final EmbeddableDomainType compositeType = (EmbeddableDomainType) type;
|
||||
//noinspection unchecked
|
||||
return new EmbeddedSqmPathSource(
|
||||
final EmbeddableDomainType<?> compositeType = (EmbeddableDomainType<?>) type;
|
||||
return new EmbeddedSqmPathSource<>(
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||
compositeType,
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE
|
||||
|
@ -404,11 +401,20 @@ public abstract class AbstractIdentifiableType<J>
|
|||
}
|
||||
else if ( nonAggregatedIdAttributes != null && ! nonAggregatedIdAttributes.isEmpty() ) {
|
||||
// non-aggregate composite id
|
||||
return new NonAggregatedCompositeSqmPathSource(
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||
this
|
||||
);
|
||||
if ( idClassType == null ) {
|
||||
return new NonAggregatedCompositeSqmPathSource(
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE,
|
||||
this
|
||||
);
|
||||
}
|
||||
else {
|
||||
return new EmbeddedSqmPathSource<>(
|
||||
EntityIdentifierMapping.ROLE_LOCAL_NAME,
|
||||
idClassType,
|
||||
Bindable.BindableType.SINGULAR_ATTRIBUTE
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( isIdMappingRequired() ) {
|
||||
|
|
|
@ -692,7 +692,7 @@ public abstract class AbstractManagedType<J>
|
|||
@SuppressWarnings("unchecked")
|
||||
public void addAttribute(PersistentAttribute<J,?> attribute) {
|
||||
if ( attribute instanceof SingularPersistentAttribute ) {
|
||||
declaredSingularAttributes.put( attribute.getName(), (SingularPersistentAttribute) attribute );
|
||||
declaredSingularAttributes.put( attribute.getName(), (SingularPersistentAttribute<J, ?>) attribute );
|
||||
}
|
||||
else if ( attribute instanceof PluralPersistentAttribute ) {
|
||||
if ( AbstractManagedType.this.declaredPluralAttributes == null ) {
|
||||
|
|
|
@ -19,7 +19,7 @@ import org.hibernate.query.sqm.SqmPathSource;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface IdentifiableDomainType<J> extends ManagedDomainType<J>, IdentifiableType<J> {
|
||||
SqmPathSource getIdentifierDescriptor();
|
||||
SqmPathSource<?> getIdentifierDescriptor();
|
||||
|
||||
@Override
|
||||
<Y> SingularPersistentAttribute<? super J, Y> getId(Class<Y> type);
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.hibernate.metamodel.RepresentationMode;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ManagedDomainType<J> extends SimpleDomainType<J>, ManagedType<J> {
|
||||
public interface ManagedDomainType<J> extends AllowableParameterType<J>, ManagedType<J> {
|
||||
/**
|
||||
* Get the type name.
|
||||
*
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.metamodel.model.domain.internal;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
|
||||
|
@ -34,7 +35,9 @@ public interface AttributeContainer<J> {
|
|||
);
|
||||
}
|
||||
|
||||
default void applyNonAggregatedIdAttributes(Set<SingularPersistentAttribute<? super J, ?>> idAttributes) {
|
||||
default void applyNonAggregatedIdAttributes(
|
||||
Set<SingularPersistentAttribute<? super J, ?>> idAttributes,
|
||||
EmbeddableDomainType<?> idClassType) {
|
||||
throw new UnsupportedOperationException(
|
||||
"AttributeContainer [" + getClass().getName() + "] does not support identifiers"
|
||||
);
|
||||
|
|
|
@ -8,6 +8,8 @@ package org.hibernate.metamodel.model.domain.internal;
|
|||
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
|
@ -18,7 +20,8 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D> {
|
||||
public class DiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>
|
||||
implements AllowableParameterType<D>, AllowableFunctionReturnType<D> {
|
||||
private final EntityDomainType<?> entityDomainType;
|
||||
private final EntityMappingType entityMapping;
|
||||
|
||||
|
@ -40,4 +43,14 @@ public class DiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D> {
|
|||
public SqmPathSource<?> findSubPathSource(String name) {
|
||||
throw new IllegalStateException( "Entity discriminator cannot be de-referenced" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceType getPersistenceType() {
|
||||
return PersistenceType.BASIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<D> getJavaType() {
|
||||
return getExpressableJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,11 @@ public class EntityDomainResultBuilder implements ResultBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return entityDescriptor.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
|
|
@ -26,6 +26,11 @@ public class ScalarDomainResultBuilder<T> implements ResultBuilder {
|
|||
this.typeDescriptor = typeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return typeDescriptor.getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<T> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
|
|
@ -57,6 +57,6 @@ public abstract class AbstractQueryParameter<T> implements QueryParameterImpleme
|
|||
|
||||
@Override
|
||||
public Class<T> getParameterType() {
|
||||
return null;
|
||||
return anticipatedType.getJavaType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
package org.hibernate.query;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.QueryException;
|
||||
|
||||
/**
|
||||
* Indicates an attempt to perform some operation on a Query that is illegal
|
||||
|
@ -16,12 +16,12 @@ import org.hibernate.HibernateException;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class IllegalQueryOperationException extends HibernateException {
|
||||
public class IllegalQueryOperationException extends QueryException {
|
||||
public IllegalQueryOperationException(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
public IllegalQueryOperationException(String message, Throwable cause) {
|
||||
super( message, cause );
|
||||
public IllegalQueryOperationException(String message, String queryString, Exception cause) {
|
||||
super( message, queryString, cause );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
|
|||
*
|
||||
* Ultimately, gets wrapped in a
|
||||
* {@link RowTransformerTupleTransformerAdapter}
|
||||
* to adapt the TupleTransformer to the {@link org.hibernate.sql.exec.spi.RowTransformer}
|
||||
* to adapt the TupleTransformer to the {@link org.hibernate.sql.results.spi.RowTransformer}
|
||||
* contract, which is the thing actually used to process the results internally.
|
||||
*
|
||||
* Note that {@link JpaTupleTransformer} is a special sub-type applications may use
|
||||
|
@ -22,7 +22,7 @@ import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
|
|||
* return type as Tuple
|
||||
*
|
||||
* @see org.hibernate.transform.ResultTransformer
|
||||
* @see org.hibernate.sql.exec.spi.RowTransformer
|
||||
* @see org.hibernate.sql.results.spi.RowTransformer
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
|
|
|
@ -646,6 +646,7 @@ public class QuerySplitter {
|
|||
return new SqmNamedParameter(
|
||||
expression.getName(),
|
||||
expression.allowMultiValuedBinding(),
|
||||
expression.getNodeType(),
|
||||
expression.nodeBuilder()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.time.ZonedDateTime;
|
|||
import java.util.Calendar;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.AllowableTemporalParameterType;
|
||||
import org.hibernate.type.CalendarDateType;
|
||||
|
@ -23,6 +24,7 @@ import org.hibernate.type.OffsetDateTimeType;
|
|||
import org.hibernate.type.OffsetTimeType;
|
||||
import org.hibernate.type.TimestampType;
|
||||
import org.hibernate.type.ZonedDateTimeType;
|
||||
import org.hibernate.type.descriptor.java.TemporalJavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -96,6 +98,29 @@ public class BindingTypeHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public JdbcMapping resolveBindType(Object value, JdbcMapping baseType) {
|
||||
if ( value == null || !( baseType.getJavaTypeDescriptor() instanceof TemporalJavaTypeDescriptor<?> ) ) {
|
||||
return baseType;
|
||||
}
|
||||
|
||||
final Class<?> javaType = value.getClass();
|
||||
final TemporalType temporalType = ( (TemporalJavaTypeDescriptor<?>) baseType.getJavaTypeDescriptor() ).getPrecision();
|
||||
switch ( temporalType ) {
|
||||
case TIMESTAMP: {
|
||||
return (JdbcMapping) resolveTimestampTemporalTypeVariant( javaType, (AllowableParameterType<?>) baseType );
|
||||
}
|
||||
case DATE: {
|
||||
return (JdbcMapping) resolveDateTemporalTypeVariant( javaType, (AllowableParameterType<?>) baseType );
|
||||
}
|
||||
case TIME: {
|
||||
return (JdbcMapping) resolveTimeTemporalTypeVariant( javaType, (AllowableParameterType<?>) baseType );
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException( "Unexpected TemporalType [" + temporalType + "]; expecting TIMESTAMP, DATE or TIME" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AllowableParameterType resolveTimestampTemporalTypeVariant(Class javaType, AllowableParameterType baseType) {
|
||||
//noinspection unchecked
|
||||
if ( baseType.getExpressableJavaTypeDescriptor().getJavaTypeClass().isAssignableFrom( javaType ) ) {
|
||||
|
|
|
@ -266,6 +266,13 @@ public class ParameterMetadataImpl implements ParameterMetadataImplementor {
|
|||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Could not locate ordinal parameter [%s], expecting one of [%s]",
|
||||
positionLabel,
|
||||
StringHelper.join( ", ", labels)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,11 +106,13 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
|
|||
return;
|
||||
}
|
||||
|
||||
if ( bindType != null ) {
|
||||
value = bindType.getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
else if ( queryParameter.getHibernateType() != null ) {
|
||||
value = queryParameter.getHibernateType().getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
if ( ! getTypeConfiguration().getSessionFactory().getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled() ) {
|
||||
if ( bindType != null ) {
|
||||
value = bindType.getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
else if ( queryParameter.getHibernateType() != null ) {
|
||||
value = queryParameter.getHibernateType().getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isBindingValidationRequired ) {
|
||||
|
@ -162,11 +164,13 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
|
|||
this.bindType = clarifiedType;
|
||||
}
|
||||
|
||||
if ( bindType != null ) {
|
||||
value = bindType.getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
else if ( queryParameter.getHibernateType() != null ) {
|
||||
value = queryParameter.getHibernateType().getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
if ( ! getTypeConfiguration().getSessionFactory().getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled() ) {
|
||||
if ( bindType != null ) {
|
||||
value = bindType.getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
else if ( queryParameter.getHibernateType() != null ) {
|
||||
value = queryParameter.getHibernateType().getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isBindingValidationRequired ) {
|
||||
|
@ -186,25 +190,27 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
|
|||
bindType = queryParameter.getHibernateType();
|
||||
}
|
||||
|
||||
if ( bindType != null ) {
|
||||
try {
|
||||
value = bindType.getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
if ( ! getTypeConfiguration().getSessionFactory().getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled() ) {
|
||||
if ( bindType != null ) {
|
||||
try {
|
||||
value = bindType.getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
catch (CoercionException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Parameter value [%s] did not match expected type [%s (%s)]",
|
||||
value,
|
||||
bindType.getTypeName(),
|
||||
temporalTypePrecision == null ? "n/a" : temporalTypePrecision.name()
|
||||
),
|
||||
ex
|
||||
);
|
||||
}
|
||||
}
|
||||
catch ( CoercionException ex ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Parameter value [%s] did not match expected type [%s (%s)]",
|
||||
value,
|
||||
bindType.getTypeName(),
|
||||
temporalTypePrecision == null ? "n/a" : temporalTypePrecision.name()
|
||||
),
|
||||
ex
|
||||
);
|
||||
else if ( queryParameter.getHibernateType() != null ) {
|
||||
value = queryParameter.getHibernateType().getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
}
|
||||
else if ( queryParameter.getHibernateType() != null ) {
|
||||
value = queryParameter.getHibernateType().getExpressableJavaTypeDescriptor().coerce( value, this );
|
||||
}
|
||||
|
||||
if ( isBindingValidationRequired ) {
|
||||
validate( value, temporalTypePrecision );
|
||||
|
|
|
@ -148,13 +148,8 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
|||
|
||||
@Override
|
||||
public <P> QueryParameterBinding<P> getBinding(String name) {
|
||||
final QueryParameterImplementor<?> parameter = parameterMetadata.getQueryParameter( name );
|
||||
if ( parameter == null ) {
|
||||
throw new IllegalArgumentException( "Parameter does not exist: " + name );
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return (QueryParameterBinding<P>) getBinding( parameter );
|
||||
return (QueryParameterBinding<P>) getBinding( parameterMetadata.getQueryParameter( name ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,8 +9,10 @@ package org.hibernate.query.internal;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
@ -21,6 +23,7 @@ import org.hibernate.query.results.BasicValuedFetchBuilder;
|
|||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.ResultBuilderEntityValued;
|
||||
import org.hibernate.query.results.complete.CompleteResultBuilderEntityJpa;
|
||||
import org.hibernate.query.results.complete.DelayedFetchBuilderBasicPart;
|
||||
import org.hibernate.query.results.implicit.ImplicitFetchBuilderBasic;
|
||||
|
||||
/**
|
||||
|
@ -71,12 +74,32 @@ public class ResultMementoEntityJpa implements ResultMementoEntity, FetchMemento
|
|||
|
||||
final HashMap<String, FetchBuilder> explicitFetchBuilderMap = new HashMap<>();
|
||||
|
||||
explicitFetchMementoMap.forEach(
|
||||
(relativePath, fetchMemento) -> explicitFetchBuilderMap.put(
|
||||
relativePath,
|
||||
fetchMemento.resolve(this, querySpaceConsumer, context )
|
||||
)
|
||||
);
|
||||
// If there are no explicit fetches, we don't register DELAYED builders to get implicit fetching of all basic fetchables
|
||||
if ( !explicitFetchMementoMap.isEmpty() ) {
|
||||
explicitFetchMementoMap.forEach(
|
||||
(relativePath, fetchMemento) -> explicitFetchBuilderMap.put(
|
||||
relativePath,
|
||||
fetchMemento.resolve( this, querySpaceConsumer, context )
|
||||
)
|
||||
);
|
||||
|
||||
// Implicit basic fetches are DELAYED by default, so register fetch builders for the remaining basic fetchables
|
||||
entityDescriptor.visitAttributeMappings(
|
||||
attributeMapping -> {
|
||||
final Function<String, FetchBuilder> fetchBuilderCreator;
|
||||
if ( attributeMapping instanceof BasicValuedModelPart ) {
|
||||
fetchBuilderCreator = k -> new DelayedFetchBuilderBasicPart(
|
||||
navigablePath.append( k ),
|
||||
(BasicValuedModelPart) attributeMapping
|
||||
);
|
||||
explicitFetchBuilderMap.computeIfAbsent(
|
||||
attributeMapping.getFetchableName(),
|
||||
fetchBuilderCreator
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return new CompleteResultBuilderEntityJpa(
|
||||
navigablePath,
|
||||
|
|
|
@ -124,12 +124,12 @@ public class Builders {
|
|||
|
||||
public static ResultBuilderBasicValued scalar(int position) {
|
||||
// will be needed for interpreting legacy HBM <resultset/> mappings
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
return new DynamicResultBuilderBasicStandard( position );
|
||||
}
|
||||
|
||||
public static ResultBuilderBasicValued scalar(int position, BasicType<?> type) {
|
||||
// will be needed for interpreting legacy HBM <resultset/> mappings
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
return new DynamicResultBuilderBasicStandard( position, type );
|
||||
}
|
||||
|
||||
public static <J> DynamicResultBuilderInstantiation<J> instantiation(Class<J> targetJavaType, SessionFactoryImplementor factory) {
|
||||
|
|
|
@ -29,6 +29,8 @@ public interface ResultBuilder {
|
|||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
DomainResultCreationState domainResultCreationState);
|
||||
|
||||
Class<?> getJavaType();
|
||||
|
||||
default void visitFetchBuilders(BiConsumer<String, FetchBuilder> consumer) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,11 @@ public class CompleteResultBuilderBasicModelPart
|
|||
this.columnAlias = columnAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return modelPart.getExpressableJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
|
|
|
@ -51,6 +51,11 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
|
|||
this.explicitJavaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return explicitJavaTypeDescriptor.getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
|
|
@ -64,6 +64,11 @@ public class CompleteResultBuilderCollectionStandard implements CompleteResultBu
|
|||
this.elementColumnNames = elementColumnNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return pluralAttributeDescriptor.getExpressableJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return tableAlias;
|
||||
|
|
|
@ -62,6 +62,11 @@ public class CompleteResultBuilderEntityJpa implements CompleteResultBuilderEnti
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return entityDescriptor.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
|
|
|
@ -50,6 +50,11 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
|||
this.explicitFetchBuilderMap = explicitFetchBuilderMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return entityDescriptor.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
|
|
|
@ -39,6 +39,11 @@ public class CompleteResultBuilderInstantiation
|
|||
this.argumentResultBuilders = argumentResultBuilders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return javaTypeDescriptor.getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
|
|
@ -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.complete;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.results.BasicValuedFetchBuilder;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class DelayedFetchBuilderBasicPart
|
||||
implements CompleteFetchBuilder, BasicValuedFetchBuilder, ModelPartReferenceBasic {
|
||||
private final NavigablePath navigablePath;
|
||||
private final BasicValuedModelPart referencedModelPart;
|
||||
|
||||
public DelayedFetchBuilderBasicPart(
|
||||
NavigablePath navigablePath,
|
||||
BasicValuedModelPart referencedModelPart) {
|
||||
this.navigablePath = navigablePath;
|
||||
this.referencedModelPart = referencedModelPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return navigablePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicValuedModelPart getReferencedPart() {
|
||||
return referencedModelPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicFetch<?> buildFetch(
|
||||
FetchParent parent,
|
||||
NavigablePath fetchPath,
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
|
||||
DomainResultCreationState domainResultCreationState) {
|
||||
return new BasicFetch<>(
|
||||
-1,
|
||||
parent,
|
||||
fetchPath,
|
||||
referencedModelPart,
|
||||
true,
|
||||
null,
|
||||
FetchTiming.DELAYED,
|
||||
domainResultCreationState
|
||||
);
|
||||
}
|
||||
}
|
|
@ -55,6 +55,11 @@ public class DynamicResultBuilderAttribute implements DynamicResultBuilder, Nati
|
|||
this.attributePath = attributePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return attributeMapping.getExpressableJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.ReturnProperty addColumnAlias(String columnAlias) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -92,6 +92,11 @@ public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBui
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return domainJtd.getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
*/
|
||||
public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBasic {
|
||||
private final String columnName;
|
||||
private final int columnPosition;
|
||||
private final String resultAlias;
|
||||
|
||||
private final BasicType<?> explicitType;
|
||||
|
@ -38,15 +39,27 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
|
|||
public DynamicResultBuilderBasicStandard(String columnName, String resultAlias) {
|
||||
assert columnName != null;
|
||||
this.columnName = columnName;
|
||||
this.columnPosition = 0;
|
||||
this.resultAlias = resultAlias != null ? resultAlias : columnName;
|
||||
|
||||
this.explicitType = null;
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
public DynamicResultBuilderBasicStandard(int columnPosition) {
|
||||
assert columnPosition > 0;
|
||||
this.columnName = "c" + columnPosition;
|
||||
this.columnPosition = columnPosition;
|
||||
this.resultAlias = columnName;
|
||||
|
||||
this.explicitType = null;
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
public DynamicResultBuilderBasicStandard(String columnName, String resultAlias, JavaTypeDescriptor<?> explicitJavaTypeDescriptor) {
|
||||
assert columnName != null;
|
||||
this.columnName = columnName;
|
||||
this.columnPosition = 0;
|
||||
this.resultAlias = resultAlias != null ? resultAlias : columnName;
|
||||
|
||||
assert explicitJavaTypeDescriptor != null;
|
||||
|
@ -58,6 +71,7 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
|
|||
public DynamicResultBuilderBasicStandard(String columnName, String resultAlias, BasicType<?> explicitType) {
|
||||
assert columnName != null;
|
||||
this.columnName = columnName;
|
||||
this.columnPosition = 0;
|
||||
this.resultAlias = resultAlias != null ? resultAlias : columnName;
|
||||
|
||||
assert explicitType != null;
|
||||
|
@ -66,6 +80,29 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
|
|||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
public DynamicResultBuilderBasicStandard(int columnPosition, BasicType<?> explicitType) {
|
||||
assert columnPosition > 0;
|
||||
this.columnName = "c" + columnPosition;
|
||||
this.columnPosition = columnPosition;
|
||||
this.resultAlias = columnName;
|
||||
|
||||
assert explicitType != null;
|
||||
this.explicitType = explicitType;
|
||||
|
||||
this.explicitJavaTypeDescriptor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
if ( explicitJavaTypeDescriptor != null ) {
|
||||
return explicitJavaTypeDescriptor.getJavaTypeClass();
|
||||
}
|
||||
if ( explicitType != null ) {
|
||||
return explicitType.getJavaType();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getColumnName() {
|
||||
return columnName;
|
||||
}
|
||||
|
@ -84,7 +121,13 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
|
|||
final Expression expression = sqlExpressionResolver.resolveSqlExpression(
|
||||
columnName,
|
||||
state -> {
|
||||
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnName );
|
||||
final int jdbcPosition;
|
||||
if ( columnPosition > 0 ) {
|
||||
jdbcPosition = columnPosition;
|
||||
}
|
||||
else {
|
||||
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnName );
|
||||
}
|
||||
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||
|
||||
final BasicType<?> basicType;
|
||||
|
|
|
@ -49,6 +49,11 @@ public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilde
|
|||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return entityMapping.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getEntityMapping() {
|
||||
return entityMapping;
|
||||
|
|
|
@ -71,6 +71,11 @@ public class DynamicResultBuilderEntityStandard
|
|||
this.tableAlias = tableAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return entityMapping.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getEntityMapping() {
|
||||
return entityMapping;
|
||||
|
|
|
@ -44,6 +44,11 @@ public class DynamicResultBuilderInstantiation<J>
|
|||
this.javaTypeDescriptor = javaTypeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return javaTypeDescriptor.getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeQuery.InstantiationResultNode<J> addBasicArgument(String columnAlias, String argumentAlias) {
|
||||
argumentResultBuilders.add(
|
||||
|
|
|
@ -32,6 +32,11 @@ public class ImplicitModelPartResultBuilderBasic
|
|||
this.modelPart = modelPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return modelPart.getExpressableJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicResult<?> buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
|
|
@ -37,6 +37,11 @@ public class ImplicitModelPartResultBuilderEmbeddable
|
|||
this.modelPart = modelPart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return modelPart.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbeddableResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
|
|
@ -40,6 +40,11 @@ public class ImplicitModelPartResultBuilderEntity
|
|||
this( new NavigablePath( entityMappingType.getEntityName() ), entityMappingType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getJavaType() {
|
||||
return modelPart.getJavaTypeDescriptor().getJavaTypeClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityResult buildResult(
|
||||
JdbcValuesMetadata jdbcResultsMetadata,
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.hibernate.internal.EntityManagerMessageLogger;
|
|||
import org.hibernate.internal.HEMLogging;
|
||||
import org.hibernate.internal.log.DeprecationLogger;
|
||||
import org.hibernate.jpa.QueryHints;
|
||||
import org.hibernate.jpa.internal.util.CacheModeHelper;
|
||||
import org.hibernate.jpa.internal.util.ConfigurationHelper;
|
||||
import org.hibernate.jpa.internal.util.FlushModeTypeHelper;
|
||||
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
||||
|
@ -66,7 +65,6 @@ import org.hibernate.query.TypedParameterValue;
|
|||
import org.hibernate.query.internal.ScrollableResultsIterator;
|
||||
import org.hibernate.query.named.NamedQueryMemento;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.JavaObjectType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
import static org.hibernate.LockMode.UPGRADE;
|
||||
|
@ -82,7 +80,6 @@ import static org.hibernate.cfg.AvailableSettings.JPA_LOCK_TIMEOUT;
|
|||
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_RETRIEVE_MODE;
|
||||
import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_STORE_MODE;
|
||||
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
|
||||
import static org.hibernate.internal.util.NullnessHelper.nullif;
|
||||
import static org.hibernate.annotations.QueryHints.NATIVE_LOCKMODE;
|
||||
import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE;
|
||||
import static org.hibernate.jpa.QueryHints.HINT_CACHE_MODE;
|
||||
|
@ -420,8 +417,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
putIfNotNull( hints, HINT_CACHE_MODE, getCacheMode() );
|
||||
putIfNotNull( hints, JAKARTA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.interpretCacheRetrieveMode( getCacheMode() ) );
|
||||
putIfNotNull( hints, JAKARTA_SHARED_CACHE_STORE_MODE, CacheModeHelper.interpretCacheStoreMode( getCacheMode() ) );
|
||||
putIfNotNull( hints, JPA_SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.interpretCacheRetrieveMode( getCacheMode() ) );
|
||||
putIfNotNull( hints, JPA_SHARED_CACHE_STORE_MODE, CacheModeHelper.interpretCacheStoreMode( getCacheMode() ) );
|
||||
putIfNotNull( hints, JPA_SHARED_CACHE_RETRIEVE_MODE, getQueryOptions().getCacheRetrieveMode() );
|
||||
putIfNotNull( hints, JPA_SHARED_CACHE_STORE_MODE, getQueryOptions().getCacheStoreMode() );
|
||||
}
|
||||
|
||||
if ( isCacheable() ) {
|
||||
|
@ -575,25 +572,13 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected boolean applyJpaCacheRetrieveMode(CacheRetrieveMode retrieveMode) {
|
||||
final CacheMode currentCacheMode = nullif( getCacheMode(), getSession().getCacheMode() );
|
||||
setCacheMode(
|
||||
CacheModeHelper.interpretCacheMode(
|
||||
CacheModeHelper.interpretCacheStoreMode( currentCacheMode ),
|
||||
retrieveMode
|
||||
)
|
||||
);
|
||||
getQueryOptions().setCacheRetrieveMode( retrieveMode );
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected boolean applyJpaCacheStoreMode(CacheStoreMode storeMode) {
|
||||
final CacheMode currentCacheMode = nullif( getCacheMode(), getSession().getCacheMode() );
|
||||
setCacheMode(
|
||||
CacheModeHelper.interpretCacheMode(
|
||||
storeMode,
|
||||
CacheModeHelper.interpretCacheRetrieveMode( currentCacheMode )
|
||||
)
|
||||
);
|
||||
getQueryOptions().setCacheStoreMode( storeMode );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ public class NativeNonSelectQueryPlanImpl implements NonSelectQueryPlan {
|
|||
final JdbcMutationExecutor executor = StandardJdbcMutationExecutor.INSTANCE;
|
||||
|
||||
final SharedSessionContractImplementor session = executionContext.getSession();
|
||||
// TODO: use configurable executor instead?
|
||||
// todo (6.0): use configurable executor instead?
|
||||
// final SessionFactoryImplementor factory = session.getFactory();
|
||||
// final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||
// return jdbcServices.getJdbcMutationExecutor().execute(
|
||||
|
|
|
@ -29,6 +29,7 @@ import jakarta.persistence.LockModeType;
|
|||
import jakarta.persistence.Parameter;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
import jakarta.persistence.TemporalType;
|
||||
import jakarta.persistence.Tuple;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
|
@ -48,6 +49,7 @@ import org.hibernate.graph.spi.RootGraphImplementor;
|
|||
import org.hibernate.internal.AbstractSharedSessionContract;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.jpa.spi.NativeQueryTupleTransformer;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
|
@ -187,7 +189,11 @@ public class NativeQueryImpl<R>
|
|||
this.sqlString = parameterInterpretation.getAdjustedSqlString();
|
||||
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
|
||||
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from(
|
||||
parameterMetadata,
|
||||
session.getFactory(),
|
||||
session.isQueryParametersValidationEnabled()
|
||||
);
|
||||
this.querySpaces = new HashSet<>();
|
||||
|
||||
this.resultSetMapping = resultSetMappingCreator.get();
|
||||
|
@ -218,21 +224,71 @@ public class NativeQueryImpl<R>
|
|||
return new ResultSetMappingImpl( mappingIdentifier );
|
||||
},
|
||||
(resultSetMapping, querySpaceConsumer, context) -> {
|
||||
if ( resultJavaType != null ) {
|
||||
|
||||
// todo (6.0) : really `resultJavaType` could be any type nature - basic, embedded, entity
|
||||
if ( memento.getResultMappingName() != null ) {
|
||||
final NamedResultSetMappingMemento resultSetMappingMemento = session.getFactory()
|
||||
.getQueryEngine()
|
||||
.getNamedObjectRepository()
|
||||
.getResultSetMappingMemento( memento.getResultMappingName() );
|
||||
if ( resultSetMappingMemento != null ) {
|
||||
resultSetMappingMemento.resolve( resultSetMapping, querySpaceConsumer, context );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( memento.getResultMappingClass() != null ) {
|
||||
resultSetMapping.addResultBuilder(
|
||||
Builders.implicitEntityResultBuilder( resultJavaType, context )
|
||||
Builders.implicitEntityResultBuilder(
|
||||
memento.getResultMappingClass(),
|
||||
context
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
if ( resultJavaType != null && resultJavaType != Tuple.class ) {
|
||||
// todo (6.0): in 5.x we didn't add implicit result builders and by doing so,
|
||||
// the result type check at the end of the constructor will fail like in 5.x
|
||||
// final JpaMetamodel jpaMetamodel = context.getSessionFactory().getJpaMetamodel();
|
||||
// if ( jpaMetamodel.findEntityType( resultJavaType ) != null ) {
|
||||
// resultSetMapping.addResultBuilder(
|
||||
// Builders.implicitEntityResultBuilder( resultJavaType, context )
|
||||
// );
|
||||
// }
|
||||
// else {
|
||||
// resultSetMapping.addResultBuilder(
|
||||
// Builders.scalar(
|
||||
// 1,
|
||||
// context.getSessionFactory()
|
||||
// .getTypeConfiguration()
|
||||
// .getBasicTypeForJavaType( resultJavaType )
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
session
|
||||
);
|
||||
|
||||
if ( resultJavaType == Tuple.class ) {
|
||||
setTupleTransformer( new NativeQueryTupleTransformer() );
|
||||
}
|
||||
else if ( resultJavaType != null ) {
|
||||
switch ( resultSetMapping.getNumberOfResultBuilders() ) {
|
||||
case 0:
|
||||
throw new IllegalArgumentException( "Named query exists but its result type is not compatible" );
|
||||
case 1:
|
||||
final Class<?> actualResultJavaType = resultSetMapping.getResultBuilders().get( 0 ).getJavaType();
|
||||
if ( !resultJavaType.isAssignableFrom( actualResultJavaType ) ) {
|
||||
throw buildIncompatibleException( resultJavaType, actualResultJavaType );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -270,7 +326,11 @@ public class NativeQueryImpl<R>
|
|||
this.sqlString = parameterInterpretation.getAdjustedSqlString();
|
||||
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
|
||||
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from(
|
||||
parameterMetadata,
|
||||
session.getFactory(),
|
||||
session.isQueryParametersValidationEnabled()
|
||||
);
|
||||
this.querySpaces = new HashSet<>();
|
||||
|
||||
this.resultSetMapping = new ResultSetMappingImpl( resultSetMappingMemento.getName() );
|
||||
|
@ -325,12 +385,36 @@ public class NativeQueryImpl<R>
|
|||
this.sqlString = parameterInterpretation.getAdjustedSqlString();
|
||||
this.parameterMetadata = parameterInterpretation.toParameterMetadata( session );
|
||||
this.occurrenceOrderedParamList = parameterInterpretation.getOccurrenceOrderedParameters();
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, session.getFactory() );
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from(
|
||||
parameterMetadata,
|
||||
session.getFactory(),
|
||||
session.isQueryParametersValidationEnabled()
|
||||
);
|
||||
|
||||
this.resultSetMapping = new ResultSetMappingImpl( sqlString );
|
||||
this.resultMappingSuppliedToCtor = false;
|
||||
}
|
||||
|
||||
private IllegalArgumentException buildIncompatibleException(Class<?> resultClass, Class<?> actualResultClass) {
|
||||
final String resultClassName = resultClass.getName();
|
||||
final String actualResultClassName = actualResultClass.getName();
|
||||
if ( resultClassName.equals( actualResultClassName ) ) {
|
||||
return new IllegalArgumentException(
|
||||
"Type specified for TypedQuery [" + resultClassName +
|
||||
"] is incompatible with the query return type of the same name." +
|
||||
" Both classes have the same name but are different as they have been loaded respectively by Classloaders " +
|
||||
resultClass.getClassLoader().toString() + ", " + actualResultClass.getClassLoader().toString() +
|
||||
". This suggests a classloader bug in the Runtime executing Hibernate ORM, or in the integration code."
|
||||
);
|
||||
}
|
||||
else {
|
||||
return new IllegalArgumentException(
|
||||
"Type specified for TypedQuery [" + resultClassName +
|
||||
"] is incompatible with query return type [" + actualResultClass + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString() {
|
||||
return sqlString;
|
||||
|
@ -516,8 +600,6 @@ public class NativeQueryImpl<R>
|
|||
}
|
||||
|
||||
private NativeSelectQueryPlan<R> createQueryPlan(ResultSetMapping resultSetMapping) {
|
||||
final RowTransformer<?> rowTransformer = null;
|
||||
|
||||
final NativeSelectQueryDefinition queryDefinition = new NativeSelectQueryDefinition() {
|
||||
@Override
|
||||
public String getSqlString() {
|
||||
|
@ -539,11 +621,6 @@ public class NativeQueryImpl<R>
|
|||
return resultSetMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RowTransformer getRowTransformer() {
|
||||
return rowTransformer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAffectedTableNames() {
|
||||
return querySpaces;
|
||||
|
@ -589,26 +666,6 @@ public class NativeQueryImpl<R>
|
|||
return resolveSelectQueryPlan().performScroll( scrollMode, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeQuery(boolean txnRequired) {
|
||||
super.beforeQuery( txnRequired );
|
||||
|
||||
if ( getSynchronizedQuerySpaces() != null && !getSynchronizedQuerySpaces().isEmpty() ) {
|
||||
// The application defined query spaces on the Hibernate native SQLQuery which means the query will already
|
||||
// perform a partial flush according to the defined query spaces, no need to do a full flush.
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise we need to flush. the query itself is not required to execute in a transaction; if there is
|
||||
// no transaction, the flush would throw a TransactionRequiredException which would potentially break existing
|
||||
// apps, so we only do the flush if a transaction is in progress.
|
||||
//
|
||||
// NOTE : this was added for JPA initially. Perhaps we want to only do this from JPA usage?
|
||||
if ( shouldFlush() ) {
|
||||
getSession().flush();
|
||||
}
|
||||
}
|
||||
|
||||
protected int doExecuteUpdate() {
|
||||
return resolveNonSelectQueryPlan().executeUpdate( this );
|
||||
}
|
||||
|
|
|
@ -33,10 +33,8 @@ 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.spi.ListResultsConsumer;
|
||||
import org.hibernate.sql.results.spi.RowTransformer;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
|
@ -49,23 +47,18 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
|
|||
private final List<QueryParameterImplementor<?>> parameterList;
|
||||
|
||||
private final JdbcValuesMappingProducer resultSetMapping;
|
||||
private final RowTransformer<R> rowTransformer;
|
||||
|
||||
public NativeSelectQueryPlanImpl(
|
||||
String sql,
|
||||
Set<String> affectedTableNames,
|
||||
List<QueryParameterImplementor<?>> parameterList,
|
||||
ResultSetMapping resultSetMapping,
|
||||
RowTransformer<R> rowTransformer,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final ResultSetMappingProcessor processor = new ResultSetMappingProcessor( resultSetMapping, sessionFactory );
|
||||
final SQLQueryParser parser = new SQLQueryParser( sql, processor.process(), sessionFactory );
|
||||
this.sql = parser.process();
|
||||
this.parameterList = parameterList;
|
||||
this.resultSetMapping = processor.generateResultMapping( parser.queryHasAliases() );
|
||||
this.rowTransformer = rowTransformer != null
|
||||
? rowTransformer
|
||||
: RowTransformerPassThruImpl.instance();
|
||||
if ( affectedTableNames == null ) {
|
||||
affectedTableNames = new HashSet<>();
|
||||
}
|
||||
|
@ -126,16 +119,16 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
|
|||
|
||||
final JdbcSelectExecutor executor = JdbcSelectExecutorStandardImpl.INSTANCE;
|
||||
|
||||
// TODO: use configurable executor instead?
|
||||
// todo (6.0): use configurable executor instead?
|
||||
// final SharedSessionContractImplementor session = executionContext.getSession();
|
||||
// final SessionFactoryImplementor factory = session.getFactory();
|
||||
// final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||
// return jdbcServices.getJdbcMutationExecutor().execute(
|
||||
// return jdbcServices.getJdbcSelectExecutor().execute(
|
||||
return executor.list(
|
||||
jdbcSelect,
|
||||
jdbcParameterBindings,
|
||||
executionContext,
|
||||
rowTransformer,
|
||||
null,
|
||||
ListResultsConsumer.UniqueSemantic.NONE
|
||||
);
|
||||
}
|
||||
|
@ -149,7 +142,7 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
|
|||
final JdbcParameterBindings jdbcParameterBindings;
|
||||
|
||||
final QueryParameterBindings queryParameterBindings = executionContext.getQueryParameterBindings();
|
||||
if ( parameterList.isEmpty() ) {
|
||||
if ( parameterList == null || parameterList.isEmpty() ) {
|
||||
jdbcParameterBinders = Collections.emptyList();
|
||||
jdbcParameterBindings = JdbcParameterBindings.NO_BINDINGS;
|
||||
}
|
||||
|
@ -190,12 +183,17 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
|
|||
|
||||
final JdbcSelectExecutor executor = JdbcSelectExecutorStandardImpl.INSTANCE;
|
||||
|
||||
// todo (6.0): use configurable executor instead?
|
||||
// final SharedSessionContractImplementor session = executionContext.getSession();
|
||||
// final SessionFactoryImplementor factory = session.getFactory();
|
||||
// final JdbcServices jdbcServices = factory.getJdbcServices();
|
||||
// return jdbcServices.getJdbcSelectExecutor().scroll(
|
||||
return executor.scroll(
|
||||
jdbcSelect,
|
||||
scrollMode,
|
||||
jdbcParameterBindings,
|
||||
executionContext,
|
||||
rowTransformer
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,9 +32,6 @@ public interface NativeSelectQueryDefinition<R> {
|
|||
|
||||
Set<String> getAffectedTableNames();
|
||||
|
||||
RowTransformer<R> getRowTransformer();
|
||||
|
||||
|
||||
// todo (6.0) : drop support for executing callables via NativeQuery
|
||||
boolean isCallable();
|
||||
|
||||
|
|
|
@ -143,7 +143,11 @@ public class QuerySqmImpl<R>
|
|||
this.domainParameterXref = hqlInterpretation.getDomainParameterXref();
|
||||
this.parameterMetadata = hqlInterpretation.getParameterMetadata();
|
||||
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, producer.getFactory() );
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from(
|
||||
parameterMetadata,
|
||||
producer.getFactory(),
|
||||
producer.isQueryParametersValidationEnabled()
|
||||
);
|
||||
|
||||
applyOptions( memento );
|
||||
}
|
||||
|
@ -186,7 +190,7 @@ public class QuerySqmImpl<R>
|
|||
this.sqmStatement = hqlInterpretation.getSqmStatement();
|
||||
|
||||
if ( resultType != null ) {
|
||||
SqmUtil.verifyIsSelectStatement( sqmStatement );
|
||||
SqmUtil.verifyIsSelectStatement( sqmStatement, hqlString );
|
||||
visitQueryReturnType(
|
||||
( (SqmSelectStatement<R>) sqmStatement ).getQueryPart(),
|
||||
resultType,
|
||||
|
@ -200,7 +204,11 @@ public class QuerySqmImpl<R>
|
|||
this.parameterMetadata = hqlInterpretation.getParameterMetadata();
|
||||
this.domainParameterXref = hqlInterpretation.getDomainParameterXref();
|
||||
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, producer.getFactory() );
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from(
|
||||
parameterMetadata,
|
||||
producer.getFactory(),
|
||||
producer.isQueryParametersValidationEnabled()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,7 +221,7 @@ public class QuerySqmImpl<R>
|
|||
super( producer );
|
||||
|
||||
if ( resultType != null ) {
|
||||
SqmUtil.verifyIsSelectStatement( sqmStatement );
|
||||
SqmUtil.verifyIsSelectStatement( sqmStatement, null );
|
||||
final SqmQueryPart<R> queryPart = ( (SqmSelectStatement<R>) sqmStatement ).getQueryPart();
|
||||
// For criteria queries, we have to validate the fetch structure here
|
||||
queryPart.validateQueryGroupFetchStructure();
|
||||
|
@ -243,7 +251,11 @@ public class QuerySqmImpl<R>
|
|||
this.parameterMetadata = new ParameterMetadataImpl( domainParameterXref.getQueryParameters() );
|
||||
}
|
||||
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from( parameterMetadata, producer.getFactory() );
|
||||
this.parameterBindings = QueryParameterBindingsImpl.from(
|
||||
parameterMetadata,
|
||||
producer.getFactory(),
|
||||
producer.isQueryParametersValidationEnabled()
|
||||
);
|
||||
// Parameters might be created through HibernateCriteriaBuilder.value which we need to bind here
|
||||
for ( SqmParameter<?> sqmParameter : this.domainParameterXref.getParameterResolutions().getSqmParameters() ) {
|
||||
if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper<?> ) {
|
||||
|
@ -575,7 +587,7 @@ public class QuerySqmImpl<R>
|
|||
|
||||
@Override
|
||||
protected List<R> doList() {
|
||||
SqmUtil.verifyIsSelectStatement( getSqmStatement() );
|
||||
SqmUtil.verifyIsSelectStatement( getSqmStatement(), hqlString );
|
||||
final SqmSelectStatement<?> selectStatement = (SqmSelectStatement<?>) getSqmStatement();
|
||||
|
||||
getSession().prepareForQueryExecution( requiresTxn( getLockOptions().findGreatestLockMode() ) );
|
||||
|
@ -710,7 +722,7 @@ public class QuerySqmImpl<R>
|
|||
|
||||
@Override
|
||||
public ScrollableResultsImplementor<R> scroll(ScrollMode scrollMode) {
|
||||
SqmUtil.verifyIsSelectStatement( getSqmStatement() );
|
||||
SqmUtil.verifyIsSelectStatement( getSqmStatement(), hqlString );
|
||||
getSession().prepareForQueryExecution( requiresTxn( getLockOptions().findGreatestLockMode() ) );
|
||||
|
||||
return resolveSelectQueryPlan().performScroll( scrollMode, this );
|
||||
|
@ -718,7 +730,7 @@ public class QuerySqmImpl<R>
|
|||
|
||||
@Override
|
||||
protected int doExecuteUpdate() {
|
||||
SqmUtil.verifyIsNonSelectStatement( getSqmStatement() );
|
||||
SqmUtil.verifyIsNonSelectStatement( getSqmStatement(), hqlString );
|
||||
getSession().prepareForQueryExecution( true );
|
||||
|
||||
return resolveNonSelectQueryPlan().executeUpdate( this );
|
||||
|
|
|
@ -70,7 +70,7 @@ public class SqmUtil {
|
|||
private SqmUtil() {
|
||||
}
|
||||
|
||||
public static void verifyIsSelectStatement(SqmStatement sqm) {
|
||||
public static void verifyIsSelectStatement(SqmStatement sqm, String hqlString) {
|
||||
if ( !(sqm instanceof SqmSelectStatement) ) {
|
||||
throw new IllegalQueryOperationException(
|
||||
String.format(
|
||||
|
@ -78,12 +78,14 @@ public class SqmUtil {
|
|||
"Expecting a SELECT Query [%s], but found %s",
|
||||
SqmSelectStatement.class.getName(),
|
||||
sqm.getClass().getName()
|
||||
)
|
||||
),
|
||||
hqlString,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyIsNonSelectStatement(SqmStatement sqm) {
|
||||
public static void verifyIsNonSelectStatement(SqmStatement sqm, String hqlString) {
|
||||
if ( !(sqm instanceof SqmDmlStatement) ) {
|
||||
throw new IllegalQueryOperationException(
|
||||
String.format(
|
||||
|
@ -91,7 +93,9 @@ public class SqmUtil {
|
|||
"Expecting a non-SELECT Query [%s], but found %s",
|
||||
SqmDmlStatement.class.getName(),
|
||||
sqm.getClass().getName()
|
||||
)
|
||||
),
|
||||
hqlString,
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
|
|||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.internal.CompositeSqmPathSource;
|
||||
|
@ -2710,7 +2711,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
final MappingModelExpressable keyExpressable = getKeyExpressable( mappingModelExpressable );
|
||||
if ( keyExpressable == null ) {
|
||||
throw new IllegalArgumentException( "Could not determine type for null literal" );
|
||||
// todo (6.0): this should be fine, right?
|
||||
return new NullnessLiteral( JavaObjectType.INSTANCE );
|
||||
// throw new IllegalArgumentException( "Could not determine type for null literal" );
|
||||
}
|
||||
|
||||
final List<Expression> expressions = new ArrayList<>( keyExpressable.getJdbcTypeCount() );
|
||||
|
@ -2775,6 +2778,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
else if ( literalValue instanceof String ) {
|
||||
discriminatorValue = javaTypeDescriptor.fromString( (String) literalValue );
|
||||
}
|
||||
else if ( creationContext.getSessionFactory().getJpaMetamodel().getJpaCompliance().isLoadByIdComplianceEnabled() ) {
|
||||
discriminatorValue = literalValue;
|
||||
}
|
||||
else {
|
||||
discriminatorValue = javaTypeDescriptor.coerce( literalValue, null );
|
||||
}
|
||||
|
@ -3171,7 +3177,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
}
|
||||
|
||||
assert parameterSqmType != null;
|
||||
if ( parameterSqmType == null || parameterSqmType == StandardBasicTypes.OBJECT_TYPE ) {
|
||||
assert binding.getBindValue() == null;
|
||||
// todo (6.0): this should be fine, right?
|
||||
return StandardBasicTypes.OBJECT_TYPE;
|
||||
}
|
||||
|
||||
if ( parameterSqmType instanceof SqmPath ) {
|
||||
final SqmPath sqmPath = (SqmPath) parameterSqmType;
|
||||
|
@ -3191,16 +3201,25 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
return (BasicValuedMapping) parameterSqmType;
|
||||
}
|
||||
|
||||
if ( parameterSqmType instanceof SqmPathSource<?> ) {
|
||||
if ( parameterSqmType instanceof CompositeSqmPathSource ) {
|
||||
// Try to infer the value mapping since the other side apparently is a path source
|
||||
final MappingModelExpressable<?> inferredValueMapping = getInferredValueMapping();
|
||||
if ( inferredValueMapping != null ) {
|
||||
return inferredValueMapping;
|
||||
}
|
||||
throw new NotYetImplementedFor6Exception( "Support for embedded-valued parameters not yet implemented" );
|
||||
}
|
||||
|
||||
if ( parameterSqmType instanceof CompositeSqmPathSource ) {
|
||||
throw new NotYetImplementedFor6Exception( "Support for embedded-valued parameters not yet implemented" );
|
||||
if ( parameterSqmType instanceof SqmPathSource<?> || parameterSqmType instanceof BasicDomainType<?> ) {
|
||||
// Try to infer the value mapping since the other side apparently is a path source
|
||||
final MappingModelExpressable<?> inferredValueMapping = getInferredValueMapping();
|
||||
if ( inferredValueMapping != null ) {
|
||||
return inferredValueMapping;
|
||||
}
|
||||
return getTypeConfiguration().getBasicTypeForJavaType(
|
||||
( (SqmExpressable<?>) parameterSqmType ).getExpressableJavaTypeDescriptor()
|
||||
.getJavaTypeClass()
|
||||
);
|
||||
}
|
||||
|
||||
throw new ConversionException( "Could not determine ValueMapping for SqmParameter: " + sqmParameter );
|
||||
|
|
|
@ -19,8 +19,6 @@ public abstract class AbstractSqmSpecificPluralPartPath<T> extends AbstractSqmPa
|
|||
private final SqmPath<?> pluralDomainPath;
|
||||
private final PluralPersistentAttribute<?, ?, T> pluralAttribute;
|
||||
|
||||
private String alias;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public AbstractSqmSpecificPluralPartPath(
|
||||
NavigablePath navigablePath,
|
||||
|
@ -51,16 +49,6 @@ public abstract class AbstractSqmSpecificPluralPartPath<T> extends AbstractSqmPa
|
|||
return pluralDomainPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplicitAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExplicitAlias(String explicitAlias) {
|
||||
this.alias = explicitAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends T> SqmTreatedPath<T, S> treatAs(Class<S> treatJavaType) throws PathException {
|
||||
if ( getReferencedPathSource().getSqmPathType() instanceof EntityDomainType ) {
|
||||
|
|
|
@ -409,7 +409,7 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPathSource getIdentifierDescriptor() {
|
||||
public SqmPathSource<?> getIdentifierDescriptor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public abstract class AbstractSqmExpression<T> extends AbstractJpaSelection<T> i
|
|||
}
|
||||
|
||||
@Override
|
||||
public final void applyInferableType(SqmExpressable<?> type) {
|
||||
public void applyInferableType(SqmExpressable<?> type) {
|
||||
// if ( type == null ) {
|
||||
// return;
|
||||
// }
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.query.internal.QueryHelper;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressable;
|
||||
|
||||
/**
|
||||
* Common support for SqmParameter impls
|
||||
|
@ -25,6 +28,22 @@ public abstract class AbstractSqmParameter<T> extends AbstractSqmExpression<T> i
|
|||
this.canBeMultiValued = canBeMultiValued;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyInferableType(SqmExpressable<?> type) {
|
||||
if ( type == null ) {
|
||||
return;
|
||||
}
|
||||
else if ( type instanceof PluralPersistentAttribute<?, ?, ?> ) {
|
||||
type = ( (PluralPersistentAttribute<?, ?, ?>) type ).getElementType();
|
||||
}
|
||||
final SqmExpressable<?> oldType = getNodeType();
|
||||
|
||||
final SqmExpressable<?> newType = QueryHelper.highestPrecedenceType( oldType, type );
|
||||
if ( newType != null && newType != oldType ) {
|
||||
internalApplyInferableType( newType );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
|
|
|
@ -17,6 +17,7 @@ public class JdbcParameterBindingImpl implements JdbcParameterBinding {
|
|||
private final Object bindValue;
|
||||
|
||||
public JdbcParameterBindingImpl(JdbcMapping jdbcMapping, Object bindValue) {
|
||||
assert bindValue == null || jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass().isInstance( bindValue );
|
||||
this.jdbcMapping = jdbcMapping;
|
||||
this.bindValue = bindValue;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.cache.spi.QueryResultsCache;
|
|||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.query.TupleTransformer;
|
||||
import org.hibernate.query.internal.ScrollableResultsIterator;
|
||||
import org.hibernate.query.spi.ScrollableResultsImplementor;
|
||||
import org.hibernate.sql.exec.SqlExecLogger;
|
||||
|
@ -30,8 +31,11 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
|
|||
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.graph.DomainResult;
|
||||
import org.hibernate.sql.results.internal.ResultsHelper;
|
||||
import org.hibernate.sql.results.internal.RowProcessingStateStandardImpl;
|
||||
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
|
||||
import org.hibernate.sql.results.internal.RowTransformerTupleTransformerAdapter;
|
||||
import org.hibernate.sql.results.jdbc.internal.DeferredResultSetAccess;
|
||||
import org.hibernate.sql.results.jdbc.internal.JdbcValuesCacheHit;
|
||||
import org.hibernate.sql.results.jdbc.internal.JdbcValuesResultSetImpl;
|
||||
|
@ -181,6 +185,21 @@ public class JdbcSelectExecutorStandardImpl implements JdbcSelectExecutor {
|
|||
deferredResultSetAccess
|
||||
);
|
||||
|
||||
if ( rowTransformer == null ) {
|
||||
final TupleTransformer<R> tupleTransformer = executionContext.getQueryOptions().getTupleTransformer();
|
||||
if ( tupleTransformer == null ) {
|
||||
rowTransformer = RowTransformerPassThruImpl.instance();
|
||||
}
|
||||
else {
|
||||
final List<DomainResult<?>> domainResults = jdbcValues.getValuesMapping().getDomainResults();
|
||||
final String[] aliases = new String[domainResults.size()];
|
||||
for ( int i = 0; i < domainResults.size(); i++ ) {
|
||||
aliases[i] = domainResults.get( i ).getResultVariable();
|
||||
}
|
||||
rowTransformer = new RowTransformerTupleTransformerAdapter<>( aliases, tupleTransformer );
|
||||
}
|
||||
}
|
||||
|
||||
final boolean stats;
|
||||
long startTime = 0;
|
||||
final StatisticsImplementor statistics = executionContext.getSession().getFactory().getStatistics();
|
||||
|
|
|
@ -11,8 +11,10 @@ import java.sql.SQLException;
|
|||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
|
||||
import org.hibernate.sql.exec.spi.ExecutionContext;
|
||||
import org.hibernate.sql.exec.spi.JdbcMutation;
|
||||
|
@ -44,11 +46,23 @@ public class StandardJdbcMutationExecutor implements JdbcMutationExecutor {
|
|||
.getLogicalConnection();
|
||||
|
||||
final JdbcServices jdbcServices = session.getJdbcServices();
|
||||
|
||||
final String sql = jdbcMutation.getSql();
|
||||
final QueryOptions queryOptions = executionContext.getQueryOptions();
|
||||
final String finalSql;
|
||||
if ( queryOptions == null ) {
|
||||
finalSql = jdbcMutation.getSql();
|
||||
}
|
||||
else {
|
||||
final Dialect dialect = jdbcServices.getDialect();
|
||||
final String sql = jdbcMutation.getSql();
|
||||
finalSql = dialect.addSqlHintOrComment(
|
||||
sql,
|
||||
queryOptions,
|
||||
executionContext.getSession().getFactory().getSessionFactoryOptions().isCommentsEnabled()
|
||||
);
|
||||
}
|
||||
try {
|
||||
// prepare the query
|
||||
final PreparedStatement preparedStatement = statementCreator.apply( sql );
|
||||
final PreparedStatement preparedStatement = statementCreator.apply( finalSql );
|
||||
|
||||
try {
|
||||
if ( executionContext.getQueryOptions().getTimeout() != null ) {
|
||||
|
@ -84,7 +98,7 @@ public class StandardJdbcMutationExecutor implements JdbcMutationExecutor {
|
|||
catch (SQLException e) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert(
|
||||
e,
|
||||
"JDBC exception executing SQL [" + sql + "]"
|
||||
"JDBC exception executing SQL [" + finalSql + "]"
|
||||
);
|
||||
}
|
||||
finally {
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.function.BiConsumer;
|
|||
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.mapping.Bindable;
|
||||
import org.hibernate.query.internal.BindingTypeHelper;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||
|
@ -23,7 +24,7 @@ import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
|||
* @apiNote "Externalized" because some JDBC parameter values are
|
||||
* intrinsically part of the parameter itself and we do not need to
|
||||
* locate a JdbcParameterBinding. E.g., consider a
|
||||
* {@link org.hibernate.sql.ast.tree.expression.LiteralParameter}
|
||||
* {@link org.hibernate.sql.ast.tree.expression.LiteralAsParameter}
|
||||
* which actually encapsulates the actually literal value inside
|
||||
* itself - to create the binder and actually perform the binding
|
||||
* is only dependent on the LiteralParameter
|
||||
|
@ -79,11 +80,12 @@ public interface JdbcParameterBindings {
|
|||
value,
|
||||
clause,
|
||||
offset,
|
||||
(selectionIndex, jdbcValue, type) ->
|
||||
addBinding(
|
||||
jdbcParameters.get( selectionIndex ),
|
||||
new JdbcParameterBindingImpl( type, jdbcValue )
|
||||
)
|
||||
(selectionIndex, jdbcValue, type) -> {
|
||||
addBinding(
|
||||
jdbcParameters.get( selectionIndex ),
|
||||
new JdbcParameterBindingImpl( BindingTypeHelper.INSTANCE.resolveBindType( jdbcValue, type ), jdbcValue )
|
||||
);
|
||||
}
|
||||
,
|
||||
session
|
||||
);
|
||||
|
|
|
@ -9,6 +9,9 @@ package org.hibernate.sql.results.jdbc.internal;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.persistence.EnumType;
|
||||
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -16,6 +19,7 @@ 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.jdbc.JdbcTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptorIndicators;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -69,28 +73,60 @@ public interface ResultSetAccess extends JdbcValuesMetadata {
|
|||
|
||||
@Override
|
||||
default <J> BasicType<J> resolveType(int position, JavaTypeDescriptor<J> explicitJavaTypeDescriptor) {
|
||||
final TypeConfiguration typeConfiguration = getFactory().getTypeConfiguration();
|
||||
final JdbcServices jdbcServices = getFactory().getJdbcServices();
|
||||
try {
|
||||
final TypeConfiguration typeConfiguration = getFactory().getTypeConfiguration();
|
||||
final ResultSetMetaData metaData = getResultSet().getMetaData();
|
||||
final JdbcTypeDescriptor jdbcTypeDescriptor = jdbcServices.getDialect()
|
||||
final int columnType = metaData.getColumnType( position );
|
||||
final int scale = metaData.getScale( position );
|
||||
final int precision = metaData.getPrecision( position );
|
||||
final int length;
|
||||
if ( columnType == Types.CHAR && precision == 0 ) {
|
||||
length = metaData.getColumnDisplaySize( position );
|
||||
}
|
||||
else {
|
||||
length = precision;
|
||||
}
|
||||
final JdbcTypeDescriptor resolvedJdbcTypeDescriptor = jdbcServices.getDialect()
|
||||
.resolveSqlTypeDescriptor(
|
||||
metaData.getColumnType( position ),
|
||||
metaData.getPrecision( position ),
|
||||
metaData.getScale( position ),
|
||||
columnType,
|
||||
length,
|
||||
scale,
|
||||
typeConfiguration.getJdbcTypeDescriptorRegistry()
|
||||
);
|
||||
final JavaTypeDescriptor<J> javaTypeDescriptor;
|
||||
if ( explicitJavaTypeDescriptor == null ) {
|
||||
javaTypeDescriptor = jdbcTypeDescriptor.getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
final JdbcTypeDescriptor jdbcTypeDescriptor;
|
||||
// If there is an explicit JavaTypeDescriptor, then prefer its recommended JDBC type
|
||||
if ( explicitJavaTypeDescriptor != null ) {
|
||||
javaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
jdbcTypeDescriptor = explicitJavaTypeDescriptor.getRecommendedJdbcType(
|
||||
new JdbcTypeDescriptorIndicators() {
|
||||
@Override
|
||||
public TypeConfiguration getTypeConfiguration() {
|
||||
return typeConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getColumnLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumType getEnumeratedType() {
|
||||
return resolvedJdbcTypeDescriptor.isNumber() ? EnumType.ORDINAL : EnumType.STRING;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
else {
|
||||
javaTypeDescriptor = explicitJavaTypeDescriptor;
|
||||
jdbcTypeDescriptor = resolvedJdbcTypeDescriptor;
|
||||
javaTypeDescriptor = jdbcTypeDescriptor.getJdbcRecommendedJavaTypeMapping(
|
||||
length,
|
||||
scale,
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
return typeConfiguration.getBasicTypeRegistry().resolve(
|
||||
javaTypeDescriptor,
|
||||
jdbcTypeDescriptor
|
||||
);
|
||||
return typeConfiguration.getBasicTypeRegistry().resolve( javaTypeDescriptor, jdbcTypeDescriptor );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert(
|
||||
|
|
|
@ -197,7 +197,11 @@ public class EnumType<T extends Enum<T>>
|
|||
private BasicJavaDescriptor<?> resolveRelationalJavaTypeDescriptor(
|
||||
LocalJdbcTypeDescriptorIndicators indicators,
|
||||
EnumJavaTypeDescriptor<?> enumJavaDescriptor) {
|
||||
return enumJavaDescriptor.getRecommendedJdbcType( indicators ).getJdbcRecommendedJavaTypeMapping( typeConfiguration );
|
||||
return enumJavaDescriptor.getRecommendedJdbcType( indicators ).getJdbcRecommendedJavaTypeMapping(
|
||||
null,
|
||||
null,
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
|
||||
private jakarta.persistence.EnumType getEnumType(ParameterType reader) {
|
||||
|
|
|
@ -76,7 +76,10 @@ public class PostgresUUIDType extends AbstractSingleColumnStandardBasicType<UUID
|
|||
}
|
||||
|
||||
@Override
|
||||
public <J> BasicJavaDescriptor<J> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <J> BasicJavaDescriptor<J> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<J>) typeConfiguration.getJavaTypeDescriptorRegistry().resolveDescriptor( UUID.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,10 @@ public class BigIntTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Long.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,10 @@ public abstract class BlobTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Blob.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,10 @@ public class BooleanTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Boolean.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,10 @@ public class DateTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Date.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,10 @@ public class DecimalTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( BigDecimal.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,10 @@ public class DoubleTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Double.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,10 @@ public class FloatTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Double.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,10 @@ public class IntegerTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Integer.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,10 @@ public interface JdbcTypeDescriptor extends Serializable {
|
|||
*/
|
||||
boolean canBeRemapped();
|
||||
|
||||
default <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
default <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer precision,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
// match legacy behavior
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor(
|
||||
JdbcTypeJavaClassMappings.INSTANCE.determineJavaClassForJdbcTypeCode( getJdbcTypeCode() )
|
||||
|
|
|
@ -52,7 +52,10 @@ public class NVarcharTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( String.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,10 @@ public class RealTypeDescriptor extends FloatTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Float.class );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,10 @@ public class SmallIntTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Short.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,10 @@ public class TimeTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Time.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,10 @@ public class TimestampTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Timestamp.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,10 @@ public class TimestampWithTimeZoneDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( OffsetDateTime.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,10 @@ public class TinyIntTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Byte.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,10 @@ public class VarbinaryTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( byte[].class );
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,13 @@ public class VarcharTypeDescriptor implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
if ( length != null && length == 1 ) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Character.class );
|
||||
}
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( String.class );
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,10 @@ public class UserTypeSqlTypeAdapter<J> implements JdbcTypeDescriptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
//noinspection unchecked
|
||||
return (BasicJavaDescriptor<T>) jtd;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import jakarta.persistence.Table;
|
|||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.dialect.Oracle8iDialect;
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.testing.SkipForDialect;
|
||||
|
||||
|
@ -35,7 +35,7 @@ import org.junit.Test;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SkipForDialect(value = Oracle8iDialect.class, jiraKey = "HHH-10323")
|
||||
@SkipForDialect(value = OracleDialect.class, jiraKey = "HHH-10323")
|
||||
public class ConstructorResultNativeQueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||
@Entity( name = "Person" )
|
||||
@SqlResultSetMappings(
|
||||
|
|
|
@ -86,7 +86,7 @@ public class NamedQueryCommentTest extends BaseEntityManagerFunctionalTestCase {
|
|||
sqlStatementInterceptor.assertExecutedCount(1);
|
||||
|
||||
sqlStatementInterceptor.assertExecuted(
|
||||
"/* COMMENT_SELECT_INDEX_game_title */ select namedquery0_.id as id1_0_, namedquery0_.title as title2_0_ from game namedquery0_ where namedquery0_.title=?"
|
||||
"/* COMMENT_SELECT_INDEX_game_title */ select g1_0.id,g1_0.title from game g1_0 where g1_0.title=?"
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
@ -206,8 +206,8 @@ public class NamedQueryCommentTest extends BaseEntityManagerFunctionalTestCase {
|
|||
sqlStatementInterceptor.assertExecutedCount(1);
|
||||
|
||||
sqlStatementInterceptor.assertExecuted(
|
||||
"/* COMMENT_SELECT_INDEX_game_title */ select namedquery0_.id as id1_0_, namedquery0_.title as title2_0_ from game namedquery0_ use index (idx_game_id) where namedquery0_.title=?" )
|
||||
;
|
||||
"/* COMMENT_SELECT_INDEX_game_title */ select g1_0.id,g1_0.title from game g1_0 use index (idx_game_id) where g1_0.title=?"
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ public class NamedQueryTest extends BaseEntityManagerFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-11413")
|
||||
public void testNamedNativeQueryExceptionNoRedultDefined() {
|
||||
public void testNamedNativeQueryExceptionNoResultDefined() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
assertThrows(
|
||||
"Named query exists but its result type is not compatible",
|
||||
|
|
|
@ -8,11 +8,7 @@ package org.hibernate.orm.test.jpa.query;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Blob;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Clob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
|
@ -31,6 +27,7 @@ import jakarta.persistence.MappedSuperclass;
|
|||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.annotations.JdbcTypeCode;
|
||||
import org.hibernate.annotations.Nationalized;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.annotations.TypeDef;
|
||||
|
@ -38,27 +35,18 @@ import org.hibernate.cfg.AvailableSettings;
|
|||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.PostgreSQL81Dialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
|
||||
import org.hibernate.jpa.boot.spi.Bootstrap;
|
||||
import org.hibernate.testing.orm.jpa.PersistenceUnitDescriptorAdapter;
|
||||
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.BigDecimalTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.BooleanTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.FloatTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicBinder;
|
||||
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.jdbc.BinaryTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.CharTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
|
||||
import org.hibernate.type.descriptor.jdbc.NumericTypeDescriptor;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
|
@ -67,9 +55,6 @@ import org.hibernate.testing.TestForIssue;
|
|||
import org.hibernate.testing.junit4.CustomRunner;
|
||||
import org.hibernate.testing.orm.junit.DialectContext;
|
||||
import org.hibernate.testing.transaction.TransactionUtil;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.BasicJdbcLiteralFormatter;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -131,7 +116,7 @@ public class NativeQueryResultTypeAutoDiscoveryTest {
|
|||
@Test
|
||||
// Postgresql turns tinyints into shorts in resultsets, and advertises the type as short in the metadata.
|
||||
// Not much we can do about that.
|
||||
@SkipForDialect(PostgreSQL81Dialect.class)
|
||||
@SkipForDialect(PostgreSQLDialect.class)
|
||||
public void tinyintType() {
|
||||
createEntityManagerFactory( TinyintEntity.class );
|
||||
doTest( TinyintEntity.class, (byte)127 );
|
||||
|
@ -526,31 +511,13 @@ public class NativeQueryResultTypeAutoDiscoveryTest {
|
|||
}
|
||||
|
||||
@Entity(name = "bitEntity")
|
||||
@TypeDef(name = BooleanAsBitType.NAME, typeClass = BooleanAsBitType.class)
|
||||
public static class BitEntity extends TestedEntity<Boolean> {
|
||||
/**
|
||||
* The custom type sets the SQL type to {@link Types#BIT}
|
||||
* instead of the default {@link Types#BOOLEAN}.
|
||||
*/
|
||||
@Type(type = BooleanAsBitType.NAME)
|
||||
@JdbcTypeCode(Types.BIT)
|
||||
public Boolean getTestedProperty() {
|
||||
return testedProperty;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BooleanAsBitType extends AbstractSingleColumnStandardBasicType<Boolean> {
|
||||
public static final String NAME = "boolean_as_bit";
|
||||
|
||||
public BooleanAsBitType() {
|
||||
super( BitTypeDescriptor.INSTANCE, BooleanTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FloatAsRealType extends AbstractSingleColumnStandardBasicType<Float> {
|
||||
public static final String NAME = "float_as_real";
|
||||
|
||||
|
@ -610,87 +577,3 @@ public class NativeQueryResultTypeAutoDiscoveryTest {
|
|||
|
||||
}
|
||||
|
||||
class BitTypeDescriptor implements JdbcTypeDescriptor {
|
||||
public static final BitTypeDescriptor INSTANCE = new BitTypeDescriptor();
|
||||
|
||||
public BitTypeDescriptor() {
|
||||
}
|
||||
|
||||
public int getJdbcTypeCode() {
|
||||
return Types.BIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "BIT";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BitTypeDescriptor";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRemapped() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Boolean.class );
|
||||
}
|
||||
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||
if ( javaTypeDescriptor.getJavaType().equals(Boolean.class) ) {
|
||||
//this is to allow literals to be formatted correctly when
|
||||
//we are in the legacy Boolean-to-BIT JDBC type mapping mode
|
||||
return new BasicJdbcLiteralFormatter( javaTypeDescriptor ) {
|
||||
@Override
|
||||
public String toJdbcLiteral(Object value, Dialect dialect, WrapperOptions wrapperOptions) {
|
||||
Boolean bool = unwrap( value, Boolean.class, wrapperOptions );
|
||||
return bool ? "1" : "0";
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return (value, dialect, wrapperOptions) -> value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
st.setBoolean( index, javaTypeDescriptor.unwrap( value, Boolean.class, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setBoolean( name, javaTypeDescriptor.unwrap( value, Boolean.class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( rs.getBoolean( paramIndex ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBoolean( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBoolean( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.sql.PreparedStatement;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
@ -22,6 +23,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
@ -39,6 +41,11 @@ public class QueryParametersValidationTest extends BaseEntityManagerFunctionalTe
|
|||
return new Class[] {TestEntity.class};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addConfigOptions(Map options) {
|
||||
options.put( AvailableSettings.JPA_LOAD_BY_ID_COMPLIANCE, "true" );
|
||||
}
|
||||
|
||||
@TestForIssue(jiraKey = "HHH-11397")
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void setParameterWithWrongTypeShouldThrowIllegalArgumentException() {
|
||||
|
|
|
@ -27,8 +27,8 @@ import org.hibernate.QueryException;
|
|||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
import org.hibernate.dialect.Oracle8iDialect;
|
||||
import org.hibernate.dialect.PostgreSQL9Dialect;
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.PostgresPlusDialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
@ -382,8 +382,8 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(value = Oracle8iDialect.class, jiraKey = "HHH-10161", comment = "Cannot convert untyped null (assumed to be BINARY type) to NUMBER")
|
||||
@SkipForDialect(value = PostgreSQL9Dialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = OracleDialect.class, jiraKey = "HHH-10161", comment = "Cannot convert untyped null (assumed to be BINARY type) to NUMBER")
|
||||
@SkipForDialect(value = PostgreSQLDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = PostgresPlusDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = CockroachDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = DerbyDialect.class, comment = "Cannot convert untyped null (assumed to be VARBINARY type) to INTEGER")
|
||||
|
@ -419,10 +419,10 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-10161")
|
||||
@SkipForDialect(value = PostgreSQL9Dialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = PostgreSQLDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = PostgresPlusDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = CockroachDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = Oracle8iDialect.class, comment = "ORA-00932: inconsistent datatypes: expected NUMBER got BINARY")
|
||||
@SkipForDialect(value = OracleDialect.class, comment = "ORA-00932: inconsistent datatypes: expected NUMBER got BINARY")
|
||||
@SkipForDialect(value = DerbyDialect.class, comment = "Cannot convert untyped null (assumed to be VARBINARY type) to INTEGER")
|
||||
public void testNativeQueryNullPositionalParameterParameter() throws Exception {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
|
@ -472,8 +472,8 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(value = Oracle8iDialect.class, jiraKey = "HHH-10161", comment = "Cannot convert untyped null (assumed to be BINARY type) to NUMBER")
|
||||
@SkipForDialect(value = PostgreSQL9Dialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = OracleDialect.class, jiraKey = "HHH-10161", comment = "Cannot convert untyped null (assumed to be BINARY type) to NUMBER")
|
||||
@SkipForDialect(value = PostgreSQLDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = PostgresPlusDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = CockroachDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = DerbyDialect.class, comment = "Cannot convert untyped null (assumed to be VARBINARY type) to INTEGER")
|
||||
|
@ -509,10 +509,10 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
|||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-10161")
|
||||
@SkipForDialect(value = PostgreSQL9Dialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = PostgreSQLDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = PostgresPlusDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = CockroachDialect.class, jiraKey = "HHH-10312", comment = "Cannot convert untyped null (assumed to be bytea type) to bigint")
|
||||
@SkipForDialect(value = Oracle8iDialect.class, comment = "ORA-00932: inconsistent datatypes: expected NUMBER got BINARY")
|
||||
@SkipForDialect(value = OracleDialect.class, comment = "ORA-00932: inconsistent datatypes: expected NUMBER got BINARY")
|
||||
@SkipForDialect(value = DerbyDialect.class, comment = "Cannot convert untyped null (assumed to be VARBINARY type) to INTEGER")
|
||||
public void testNativeQueryNullNamedParameterParameter() throws Exception {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
|
|
Loading…
Reference in New Issue