Skip to content

Commit b1135b5

Browse files
committed
HHH-18728 - Allow mixed discriminator-value mappings for ANY
1 parent f82c581 commit b1135b5

File tree

17 files changed

+664
-20
lines changed

17 files changed

+664
-20
lines changed

hibernate-core/src/main/java/org/hibernate/annotations/AnyDiscriminator.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
import java.lang.annotation.Target;
99

1010
import jakarta.persistence.DiscriminatorType;
11+
import org.hibernate.type.AnyDiscriminatorValueStrategy;
1112

1213
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
1314
import static java.lang.annotation.ElementType.FIELD;
1415
import static java.lang.annotation.ElementType.METHOD;
1516
import static java.lang.annotation.RetentionPolicy.RUNTIME;
17+
import static org.hibernate.type.AnyDiscriminatorValueStrategy.AUTO;
1618

1719
/**
1820
* A simplified way to specify the type of the discriminator in an {@link Any}
@@ -44,4 +46,12 @@
4446
* or {@link JdbcTypeCode}.
4547
*/
4648
DiscriminatorType value() default DiscriminatorType.STRING;
49+
50+
/**
51+
* How the discriminator value should be handled in regard to explicit
52+
* {@linkplain AnyDiscriminatorValue} mappings, if any.
53+
*
54+
* @since 7.0
55+
*/
56+
AnyDiscriminatorValueStrategy valueStrategy() default AUTO;
4757
}

hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnyBinder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import org.hibernate.AnnotationException;
1010
import org.hibernate.AssertionFailure;
11+
import org.hibernate.annotations.AnyDiscriminator;
1112
import org.hibernate.annotations.Cascade;
1213
import org.hibernate.annotations.Columns;
1314
import org.hibernate.annotations.Formula;
@@ -107,6 +108,11 @@ private static void bindAny(
107108
context
108109
);
109110

111+
final AnyDiscriminator anyDiscriminator = property.getDirectAnnotationUsage( AnyDiscriminator.class );
112+
if ( anyDiscriminator != null ) {
113+
value.setDiscriminatorValueStrategy( anyDiscriminator.valueStrategy() );
114+
}
115+
110116
final PropertyBinder binder = new PropertyBinder();
111117
binder.setName( inferredData.getPropertyName() );
112118
binder.setValue( value );

hibernate-core/src/main/java/org/hibernate/boot/models/annotations/internal/AnyDiscriminatorAnnotation.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,28 @@
99

1010
import org.hibernate.annotations.AnyDiscriminator;
1111
import org.hibernate.models.spi.SourceModelBuildingContext;
12+
import org.hibernate.type.AnyDiscriminatorValueStrategy;
1213

1314
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
1415
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
1516
public class AnyDiscriminatorAnnotation implements AnyDiscriminator {
1617
private jakarta.persistence.DiscriminatorType value;
18+
private AnyDiscriminatorValueStrategy valueStrategy;
1719

1820
/**
1921
* Used in creating dynamic annotation instances (e.g. from XML)
2022
*/
2123
public AnyDiscriminatorAnnotation(SourceModelBuildingContext modelContext) {
2224
this.value = jakarta.persistence.DiscriminatorType.STRING;
25+
this.valueStrategy = AnyDiscriminatorValueStrategy.AUTO;
2326
}
2427

2528
/**
2629
* Used in creating annotation instances from JDK variant
2730
*/
2831
public AnyDiscriminatorAnnotation(AnyDiscriminator annotation, SourceModelBuildingContext modelContext) {
2932
this.value = annotation.value();
33+
this.valueStrategy = annotation.valueStrategy();
3034
}
3135

3236
/**
@@ -50,5 +54,14 @@ public void value(jakarta.persistence.DiscriminatorType value) {
5054
this.value = value;
5155
}
5256

57+
@Override
58+
public AnyDiscriminatorValueStrategy valueStrategy() {
59+
return valueStrategy;
60+
}
61+
62+
public void valueStrategy(AnyDiscriminatorValueStrategy valueStrategy) {
63+
this.valueStrategy = valueStrategy;
64+
}
65+
5366

5467
}

hibernate-core/src/main/java/org/hibernate/mapping/Any.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Objects;
1010
import java.util.function.Consumer;
1111

12+
import org.hibernate.Incubating;
1213
import org.hibernate.MappingException;
1314
import org.hibernate.boot.spi.MetadataBuildingContext;
1415
import org.hibernate.engine.jdbc.spi.JdbcServices;
@@ -34,6 +35,7 @@ public class Any extends SimpleValue {
3435

3536
// common
3637
private Map<Object,String> metaValueToEntityNameMap;
38+
private AnyDiscriminatorValueStrategy discriminatorValueStrategy = AnyDiscriminatorValueStrategy.AUTO;
3739
private boolean lazy = true;
3840

3941
private AnyType resolvedType;
@@ -73,6 +75,7 @@ public Any(Any original) {
7375
this.metaValueToEntityNameMap = original.metaValueToEntityNameMap == null
7476
? null
7577
: new HashMap<>(original.metaValueToEntityNameMap);
78+
this.discriminatorValueStrategy = original.discriminatorValueStrategy;
7679
this.lazy = original.lazy;
7780
}
7881

@@ -128,6 +131,28 @@ public void setIdentifierType(String identifierType) {
128131
this.keyMapping.setTypeName( identifierType );
129132
}
130133

134+
/**
135+
* Current strategy for interpreting {@linkplain org.hibernate.annotations.AnyDiscriminatorValue} definitions,
136+
* especially in terms of implicit, explicit and potentially missing values.
137+
*
138+
* @since 7.0
139+
*/
140+
@Incubating
141+
public AnyDiscriminatorValueStrategy getDiscriminatorValueStrategy() {
142+
return discriminatorValueStrategy;
143+
}
144+
145+
/**
146+
* Set the strategy
147+
*
148+
* @see #getDiscriminatorValueStrategy
149+
* @since 7.0
150+
*/
151+
@Incubating
152+
public void setDiscriminatorValueStrategy(AnyDiscriminatorValueStrategy discriminatorValueStrategy) {
153+
this.discriminatorValueStrategy = discriminatorValueStrategy;
154+
}
155+
131156
@Override
132157
public AnyType getType() throws MappingException {
133158
if ( resolvedType == null ) {
@@ -150,6 +175,7 @@ public AnyType getType() throws MappingException {
150175
resolvedType = MappingHelper.anyMapping(
151176
discriminatorType,
152177
identifierType,
178+
discriminatorValueStrategy,
153179
metaValueToEntityNameMap,
154180
isLazy(),
155181
getBuildingContext()

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/DiscriminatorConverter.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
*/
55
package org.hibernate.metamodel.mapping;
66

7+
import org.hibernate.Incubating;
78
import org.hibernate.metamodel.RepresentationMode;
9+
import org.hibernate.type.AnyDiscriminatorValueStrategy;
810
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
911
import org.hibernate.type.descriptor.java.JavaType;
1012

@@ -16,7 +18,6 @@
1618
* @author Gavin King
1719
*/
1820
public abstract class DiscriminatorConverter<O,R> implements BasicValueConverter<O,R> {
19-
2021
private final String discriminatorName;
2122
private final JavaType<O> domainJavaType;
2223
private final JavaType<R> relationalJavaType;
@@ -30,6 +31,9 @@ public DiscriminatorConverter(
3031
this.relationalJavaType = relationalJavaType;
3132
}
3233

34+
@Incubating
35+
public abstract AnyDiscriminatorValueStrategy getValueStrategy();
36+
3337
public String getDiscriminatorName() {
3438
return discriminatorName;
3539
}

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableDiscriminatorConverter.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@
44
*/
55
package org.hibernate.metamodel.mapping;
66

7-
import java.util.ArrayList;
8-
import java.util.HashMap;
9-
import java.util.List;
10-
import java.util.Map;
11-
import java.util.function.Consumer;
12-
import java.util.function.Function;
13-
147
import org.hibernate.AssertionFailure;
158
import org.hibernate.HibernateException;
169
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
1710
import org.hibernate.metamodel.mapping.internal.EmbeddableDiscriminatorValueDetailsImpl;
1811
import org.hibernate.service.ServiceRegistry;
12+
import org.hibernate.type.AnyDiscriminatorValueStrategy;
1913
import org.hibernate.type.BasicType;
2014
import org.hibernate.type.descriptor.java.JavaType;
2115

16+
import java.util.ArrayList;
17+
import java.util.HashMap;
18+
import java.util.List;
19+
import java.util.Map;
20+
import java.util.function.Consumer;
21+
import java.util.function.Function;
22+
2223
/**
2324
* Handles conversion of discriminator values for embeddable subtype classes
2425
* to their domain typed form.
@@ -65,6 +66,12 @@ public EmbeddableDiscriminatorConverter(
6566
} );
6667
}
6768

69+
@Override
70+
public AnyDiscriminatorValueStrategy getValueStrategy() {
71+
// discriminators for embeddables are always explicit
72+
return AnyDiscriminatorValueStrategy.EXPLICIT;
73+
}
74+
6875
@Override
6976
public O toDomainValue(R relationalForm) {
7077
assert relationalForm == null || getRelationalJavaType().isInstance( relationalForm );

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ExplicitDiscriminatorConverter.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.hibernate.metamodel.model.domain.NavigableRole;
1313
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
1414
import org.hibernate.persister.entity.EntityPersister;
15+
import org.hibernate.type.AnyDiscriminatorValueStrategy;
1516
import org.hibernate.type.descriptor.java.CharacterJavaType;
1617
import org.hibernate.type.descriptor.java.JavaType;
1718
import org.hibernate.type.descriptor.java.StringJavaType;
@@ -60,6 +61,19 @@ public ExplicitDiscriminatorConverter(
6061
} );
6162
}
6263

64+
@Override
65+
public AnyDiscriminatorValueStrategy getValueStrategy() {
66+
return AnyDiscriminatorValueStrategy.EXPLICIT;
67+
}
68+
69+
public Map<Object, DiscriminatorValueDetails> getDetailsByValue() {
70+
return detailsByValue;
71+
}
72+
73+
public Map<String, DiscriminatorValueDetails> getDetailsByEntityName() {
74+
return detailsByEntityName;
75+
}
76+
6377
@Override
6478
public DiscriminatorValueDetails getDetailsForDiscriminatorValue(Object relationalForm) {
6579
if ( relationalForm == null ) {
@@ -80,13 +94,13 @@ public DiscriminatorValueDetails getDetailsForDiscriminatorValue(Object relation
8094
if ( relationalForm.getClass().isEnum() ) {
8195
final Object enumValue;
8296
if ( getRelationalJavaType() instanceof StringJavaType ) {
83-
enumValue = ( (Enum) relationalForm ).name();
97+
enumValue = ( (Enum<?>) relationalForm ).name();
8498
}
8599
else if ( getRelationalJavaType() instanceof CharacterJavaType ) {
86-
enumValue = ( (Enum) relationalForm ).name().charAt( 0 );
100+
enumValue = ( (Enum<?>) relationalForm ).name().charAt( 0 );
87101
}
88102
else {
89-
enumValue = ( (Enum) relationalForm ).ordinal();
103+
enumValue = ( (Enum<?>) relationalForm ).ordinal();
90104
}
91105
final DiscriminatorValueDetails enumMatch = detailsByValue.get( enumValue );
92106
if ( enumMatch != null ) {
@@ -108,7 +122,7 @@ public DiscriminatorValueDetails getDetailsForEntityName(String entityName) {
108122
if ( valueDetails != null) {
109123
return valueDetails;
110124
}
111-
throw new HibernateException( "Unknown entity name (" + discriminatorRole + ") : " + entityName );
125+
throw new HibernateException( "Entity not explicitly mapped for ANY discriminator (" + discriminatorRole + ") : " + entityName );
112126
}
113127

114128

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ImplicitDiscriminatorConverter.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.hibernate.metamodel.model.domain.NavigableRole;
1313
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
1414
import org.hibernate.persister.entity.EntityPersister;
15+
import org.hibernate.type.AnyDiscriminatorValueStrategy;
1516
import org.hibernate.type.descriptor.java.JavaType;
1617

1718
import java.util.Map;
@@ -51,17 +52,28 @@ public ImplicitDiscriminatorConverter(
5152
this.detailsByEntityName = CollectionHelper.concurrentMap( 8 );
5253
}
5354

55+
@Override
56+
public AnyDiscriminatorValueStrategy getValueStrategy() {
57+
return AnyDiscriminatorValueStrategy.IMPLICIT;
58+
}
59+
60+
public Map<Object, DiscriminatorValueDetails> getDetailsByValue() {
61+
return detailsByValue;
62+
}
63+
64+
public Map<String, DiscriminatorValueDetails> getDetailsByEntityName() {
65+
return detailsByEntityName;
66+
}
67+
5468
@Override
5569
public DiscriminatorValueDetails getDetailsForDiscriminatorValue(Object value) {
5670
if ( value instanceof String incoming ) {
5771
final DiscriminatorValueDetails existingDetails = detailsByValue.get( incoming );
5872
if ( existingDetails != null ) {
5973
return existingDetails;
6074
}
61-
final String entityName = mappingMetamodel.getImportedName( incoming );
62-
final EntityPersister persister = mappingMetamodel.findEntityDescriptor( entityName );
75+
final EntityPersister persister = mappingMetamodel.findEntityDescriptor( incoming );
6376
if ( persister != null ) {
64-
assert persister.getImportedName().equals( incoming );
6577
return register( incoming, persister );
6678
}
6779
}
@@ -76,7 +88,7 @@ public DiscriminatorValueDetails getDetailsForDiscriminatorValue(Object value) {
7688
private DiscriminatorValueDetails register(Object value, EntityPersister entityDescriptor) {
7789
final DiscriminatorValueDetails details = new DiscriminatorValueDetailsImpl( value, entityDescriptor );
7890
detailsByValue.put( value, details );
79-
detailsByEntityName.put( entityDescriptor.getImportedName(), details );
91+
detailsByEntityName.put( entityDescriptor.getEntityName(), details );
8092
return details;
8193
}
8294

@@ -88,7 +100,7 @@ public DiscriminatorValueDetails getDetailsForEntityName(String entityName) {
88100
}
89101
final EntityPersister persister = mappingMetamodel.findEntityDescriptor( entityName );
90102
if ( persister!= null ) {
91-
return register( persister.getImportedName(), persister );
103+
return register( persister.getEntityName(), persister );
92104
}
93105
throw new HibernateException( String.format(
94106
ROOT,

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MixedDiscriminatorConverter.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.hibernate.metamodel.model.domain.NavigableRole;
1212
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
1313
import org.hibernate.persister.entity.EntityPersister;
14+
import org.hibernate.type.AnyDiscriminatorValueStrategy;
1415
import org.hibernate.type.descriptor.java.CharacterJavaType;
1516
import org.hibernate.type.descriptor.java.JavaType;
1617
import org.hibernate.type.descriptor.java.StringJavaType;
@@ -59,6 +60,19 @@ private DiscriminatorValueDetails register(Object value, EntityPersister entityD
5960
return details;
6061
}
6162

63+
@Override
64+
public AnyDiscriminatorValueStrategy getValueStrategy() {
65+
return AnyDiscriminatorValueStrategy.MIXED;
66+
}
67+
68+
public Map<Object, DiscriminatorValueDetails> getDetailsByValue() {
69+
return detailsByValue;
70+
}
71+
72+
public Map<String, DiscriminatorValueDetails> getDetailsByEntityName() {
73+
return detailsByEntityName;
74+
}
75+
6276
@Override
6377
public DiscriminatorValueDetails getDetailsForDiscriminatorValue(Object relationalForm) {
6478
if ( relationalForm == null ) {
@@ -79,13 +93,13 @@ public DiscriminatorValueDetails getDetailsForDiscriminatorValue(Object relation
7993
if ( relationalForm.getClass().isEnum() ) {
8094
final Object enumValue;
8195
if ( getRelationalJavaType() instanceof StringJavaType ) {
82-
enumValue = ( (Enum) relationalForm ).name();
96+
enumValue = ( (Enum<?>) relationalForm ).name();
8397
}
8498
else if ( getRelationalJavaType() instanceof CharacterJavaType ) {
85-
enumValue = ( (Enum) relationalForm ).name().charAt( 0 );
99+
enumValue = ( (Enum<?>) relationalForm ).name().charAt( 0 );
86100
}
87101
else {
88-
enumValue = ( (Enum) relationalForm ).ordinal();
102+
enumValue = ( (Enum<?>) relationalForm ).ordinal();
89103
}
90104
final DiscriminatorValueDetails enumMatch = detailsByValue.get( enumValue );
91105
if ( enumMatch != null ) {

hibernate-core/src/main/java/org/hibernate/type/AnyDiscriminatorValueStrategy.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package org.hibernate.type;
66

7+
import org.hibernate.Incubating;
78
import org.hibernate.annotations.AnyDiscriminatorValue;
89

910
/**
@@ -12,8 +13,10 @@
1213
*
1314
* @see AnyDiscriminatorValue
1415
*
16+
* @since 7.0
1517
* @author Steve Ebersole
1618
*/
19+
@Incubating
1720
public enum AnyDiscriminatorValueStrategy {
1821
/**
1922
* Pick between {@link #IMPLICIT} and {@link #EXPLICIT} based on

0 commit comments

Comments
 (0)