Skip to content

Commit 68a09b7

Browse files
committed
HHH-17151 Resolve explicit temporal bind type for null values
1 parent 755dd7f commit 68a09b7

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

hibernate-core/src/main/java/org/hibernate/query/internal/BindingTypeHelper.java

+30-8
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,40 @@ public <T> BindableType<T> resolveTemporalPrecision(
4141
BindableType<T> declaredParameterType,
4242
SessionFactoryImplementor sessionFactory) {
4343
if ( precision != null ) {
44-
final SqmExpressible<T> sqmExpressible = declaredParameterType.resolveExpressible( sessionFactory );
45-
if ( !( JavaTypeHelper.isTemporal( sqmExpressible.getExpressibleJavaType() ) ) ) {
46-
throw new UnsupportedOperationException(
47-
"Cannot treat non-temporal parameter type with temporal precision"
48-
);
44+
final TemporalJavaType<T> temporalJtd;
45+
if ( declaredParameterType != null ) {
46+
final SqmExpressible<T> sqmExpressible = declaredParameterType.resolveExpressible( sessionFactory );
47+
if ( !( JavaTypeHelper.isTemporal( sqmExpressible.getExpressibleJavaType() ) ) ) {
48+
throw new UnsupportedOperationException(
49+
"Cannot treat non-temporal parameter type with temporal precision"
50+
);
51+
}
52+
temporalJtd = (TemporalJavaType<T>) sqmExpressible.getExpressibleJavaType();
53+
}
54+
else {
55+
temporalJtd = null;
4956
}
5057

51-
final TemporalJavaType<T> temporalJtd = (TemporalJavaType<T>) sqmExpressible.getExpressibleJavaType();
52-
if ( temporalJtd.getPrecision() != precision ) {
58+
if ( temporalJtd == null || temporalJtd.getPrecision() != precision ) {
5359
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
60+
final TemporalJavaType<T> temporalTypeForPrecision;
61+
// Special case java.util.Date, because TemporalJavaType#resolveTypeForPrecision doesn't support widening,
62+
// since the main purpose of that method is to determine the final java type based on the reflective type
63+
// + the explicit @Temporal(TemporalType...) configuration
64+
if ( temporalJtd == null || java.util.Date.class.isAssignableFrom( temporalJtd.getJavaTypeClass() ) ) {
65+
//noinspection unchecked
66+
temporalTypeForPrecision = (TemporalJavaType<T>) typeConfiguration.getJavaTypeRegistry().getDescriptor(
67+
TemporalJavaType.resolveJavaTypeClass( precision )
68+
);
69+
}
70+
else {
71+
temporalTypeForPrecision = temporalJtd.resolveTypeForPrecision(
72+
precision,
73+
typeConfiguration
74+
);
75+
}
5476
return typeConfiguration.getBasicTypeRegistry().resolve(
55-
temporalJtd.resolveTypeForPrecision( precision, typeConfiguration ),
77+
temporalTypeForPrecision,
5678
TemporalJavaType.resolveJdbcTypeCode( precision )
5779
);
5880
}

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/TemporalJavaType.java

+12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ static int resolveJdbcTypeCode(TemporalType requestedTemporalPrecision) {
3333
throw new UnsupportedOperationException( "Unsupported precision: " + requestedTemporalPrecision );
3434
}
3535

36+
static Class<?> resolveJavaTypeClass(TemporalType requestedTemporalPrecision) {
37+
switch ( requestedTemporalPrecision ) {
38+
case DATE:
39+
return java.sql.Date.class;
40+
case TIME:
41+
return java.sql.Time.class;
42+
case TIMESTAMP:
43+
return java.sql.Timestamp.class;
44+
}
45+
throw new UnsupportedOperationException( "Unsupported precision: " + requestedTemporalPrecision );
46+
}
47+
3648
/**
3749
* The precision represented by this type
3850
*/

0 commit comments

Comments
 (0)