Skip to content

Commit 9397b1e

Browse files
committed
HHH-18728 - Allow mixed discriminator-value mappings for ANY
HHH-18729 - Allow custom strategy for implicit discriminator-value determination for ANY
1 parent 24a1b2c commit 9397b1e

25 files changed

+273
-613
lines changed

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

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

1010
import jakarta.persistence.DiscriminatorType;
11-
import org.hibernate.type.AnyDiscriminatorValueStrategy;
11+
import org.hibernate.metamodel.spi.ImplicitDiscriminatorStrategy;
1212

1313
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
1414
import static java.lang.annotation.ElementType.FIELD;
1515
import static java.lang.annotation.ElementType.METHOD;
1616
import static java.lang.annotation.RetentionPolicy.RUNTIME;
17-
import static org.hibernate.type.AnyDiscriminatorValueStrategy.AUTO;
1817

1918
/**
2019
* A simplified way to specify the type of the discriminator in an {@link Any}
@@ -48,16 +47,8 @@
4847
DiscriminatorType value() default DiscriminatorType.STRING;
4948

5049
/**
51-
* How the discriminator value should be handled in regard to explicit
52-
* {@linkplain AnyDiscriminatorValue} mappings, if any.
53-
*
54-
* @since 7.0
50+
* Determines how to handle mappings which are not explicitly defined by
51+
* any associated {@linkplain AnyDiscriminatorValue} annotations
5552
*/
56-
AnyDiscriminatorValueStrategy valueStrategy() default AUTO;
57-
58-
/**
59-
* Whether the entity's short-name should be used as the discriminator value
60-
* (as opposed to its full-name) in the case of implicit value mapping.
61-
*/
62-
boolean implicitEntityShortName() default false;
53+
Class<? extends ImplicitDiscriminatorStrategy> implicitValueStrategy() default ImplicitDiscriminatorStrategy.class;
6354
}

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import org.hibernate.mapping.Any;
2020
import org.hibernate.mapping.Join;
2121
import org.hibernate.mapping.Property;
22+
import org.hibernate.metamodel.internal.FullNameImplicitDiscriminatorStrategy;
23+
import org.hibernate.metamodel.internal.ShortNameImplicitDiscriminatorStrategy;
24+
import org.hibernate.metamodel.spi.ImplicitDiscriminatorStrategy;
2225
import org.hibernate.models.spi.MemberDetails;
2326

2427
import jakarta.persistence.Column;
@@ -110,8 +113,7 @@ private static void bindAny(
110113

111114
final AnyDiscriminator anyDiscriminator = property.getDirectAnnotationUsage( AnyDiscriminator.class );
112115
if ( anyDiscriminator != null ) {
113-
value.setDiscriminatorValueStrategy( anyDiscriminator.valueStrategy() );
114-
value.setImplicitEntityShortName( anyDiscriminator.implicitEntityShortName() );
116+
value.setImplicitDiscriminatorValueStrategy( resolveImplicitDiscriminatorStrategy( anyDiscriminator, context ) );
115117
}
116118

117119
final PropertyBinder binder = new PropertyBinder();
@@ -135,4 +137,23 @@ private static void bindAny(
135137
propertyHolder.addProperty( prop, inferredData.getAttributeMember(), columns, inferredData.getDeclaringClass() );
136138
binder.callAttributeBindersInSecondPass( prop );
137139
}
140+
141+
private static ImplicitDiscriminatorStrategy resolveImplicitDiscriminatorStrategy(
142+
AnyDiscriminator anyDiscriminator,
143+
MetadataBuildingContext context) {
144+
final Class<? extends ImplicitDiscriminatorStrategy> implicitValueStrategy = anyDiscriminator.implicitValueStrategy();
145+
if ( ImplicitDiscriminatorStrategy.class.equals( implicitValueStrategy ) ) {
146+
return null;
147+
}
148+
149+
if ( FullNameImplicitDiscriminatorStrategy.class.equals( implicitValueStrategy ) ) {
150+
return FullNameImplicitDiscriminatorStrategy.FULL_NAME_STRATEGY;
151+
}
152+
153+
if ( ShortNameImplicitDiscriminatorStrategy.class.equals( implicitValueStrategy ) ) {
154+
return ShortNameImplicitDiscriminatorStrategy.SHORT_NAME_STRATEGY;
155+
}
156+
157+
return context.getBootstrapContext().getCustomTypeProducer().produceBeanInstance( implicitValueStrategy );
158+
}
138159
}

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

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,38 @@
88
import java.util.Map;
99

1010
import org.hibernate.annotations.AnyDiscriminator;
11+
import org.hibernate.metamodel.spi.ImplicitDiscriminatorStrategy;
1112
import org.hibernate.models.spi.SourceModelBuildingContext;
12-
import org.hibernate.type.AnyDiscriminatorValueStrategy;
1313

1414
@SuppressWarnings({ "ClassExplicitlyAnnotation", "unused" })
1515
@jakarta.annotation.Generated("org.hibernate.orm.build.annotations.ClassGeneratorProcessor")
1616
public class AnyDiscriminatorAnnotation implements AnyDiscriminator {
1717
private jakarta.persistence.DiscriminatorType value;
18-
private AnyDiscriminatorValueStrategy valueStrategy;
19-
private boolean implicitEntityShortName;
18+
private Class<? extends ImplicitDiscriminatorStrategy> implicitValueStrategy;
2019

2120
/**
2221
* Used in creating dynamic annotation instances (e.g. from XML)
2322
*/
2423
public AnyDiscriminatorAnnotation(SourceModelBuildingContext modelContext) {
2524
this.value = jakarta.persistence.DiscriminatorType.STRING;
26-
this.valueStrategy = AnyDiscriminatorValueStrategy.AUTO;
27-
this.implicitEntityShortName = false;
25+
this.implicitValueStrategy = ImplicitDiscriminatorStrategy.class;
2826
}
2927

3028
/**
3129
* Used in creating annotation instances from JDK variant
3230
*/
3331
public AnyDiscriminatorAnnotation(AnyDiscriminator annotation, SourceModelBuildingContext modelContext) {
3432
this.value = annotation.value();
35-
this.valueStrategy = annotation.valueStrategy();
36-
this.implicitEntityShortName = annotation.implicitEntityShortName();
33+
this.implicitValueStrategy = annotation.implicitValueStrategy();
3734
}
3835

3936
/**
4037
* Used in creating annotation instances from Jandex variant
4138
*/
4239
public AnyDiscriminatorAnnotation(Map<String, Object> attributeValues, SourceModelBuildingContext modelContext) {
4340
this.value = (jakarta.persistence.DiscriminatorType) attributeValues.get( "value" );
44-
this.valueStrategy = (AnyDiscriminatorValueStrategy) attributeValues.get( "valueStrategy" );
45-
this.implicitEntityShortName = (boolean) attributeValues.get( "implicitEntityShortName" );
41+
//noinspection unchecked
42+
this.implicitValueStrategy = (Class<? extends ImplicitDiscriminatorStrategy>) attributeValues.get( "implicitValueStrategy" );
4643
}
4744

4845
@Override
@@ -60,20 +57,11 @@ public void value(jakarta.persistence.DiscriminatorType value) {
6057
}
6158

6259
@Override
63-
public AnyDiscriminatorValueStrategy valueStrategy() {
64-
return valueStrategy;
60+
public Class<? extends ImplicitDiscriminatorStrategy> implicitValueStrategy() {
61+
return implicitValueStrategy;
6562
}
6663

67-
public void valueStrategy(AnyDiscriminatorValueStrategy valueStrategy) {
68-
this.valueStrategy = valueStrategy;
69-
}
70-
71-
@Override
72-
public boolean implicitEntityShortName() {
73-
return implicitEntityShortName;
74-
}
75-
76-
public void implicitEntityShortName(boolean implicitEntityShortName) {
77-
this.implicitEntityShortName = implicitEntityShortName;
64+
public void implicitValueStrategy(Class<? extends ImplicitDiscriminatorStrategy> implicitValueStrategy) {
65+
this.implicitValueStrategy = implicitValueStrategy;
7866
}
7967
}

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

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import org.hibernate.MappingException;
99
import org.hibernate.boot.spi.MetadataBuildingContext;
1010
import org.hibernate.engine.jdbc.spi.JdbcServices;
11-
import org.hibernate.type.AnyDiscriminatorValueStrategy;
11+
import org.hibernate.metamodel.spi.ImplicitDiscriminatorStrategy;
1212
import org.hibernate.type.AnyType;
1313
import org.hibernate.type.MappingContext;
1414
import org.hibernate.type.Type;
@@ -35,8 +35,7 @@ public class Any extends SimpleValue {
3535

3636
// common
3737
private Map<Object,String> metaValueToEntityNameMap;
38-
private AnyDiscriminatorValueStrategy discriminatorValueStrategy = AnyDiscriminatorValueStrategy.AUTO;
39-
private boolean implicitEntityShortName = false;
38+
private ImplicitDiscriminatorStrategy implicitValueStrategy;
4039
private boolean lazy = true;
4140

4241
private AnyType resolvedType;
@@ -76,7 +75,7 @@ public Any(Any original) {
7675
this.metaValueToEntityNameMap = original.metaValueToEntityNameMap == null
7776
? null
7877
: new HashMap<>(original.metaValueToEntityNameMap);
79-
this.discriminatorValueStrategy = original.discriminatorValueStrategy;
78+
this.implicitValueStrategy = original.implicitValueStrategy;
8079
this.lazy = original.lazy;
8180
}
8281

@@ -133,24 +132,16 @@ public void setIdentifierType(String identifierType) {
133132
}
134133

135134
/**
136-
* Set the strategy for interpreting {@linkplain org.hibernate.annotations.AnyDiscriminatorValue}
137-
* definitions in terms of implicit, explicit and potentially missing values.
135+
* Set the strategy for dealing with discriminator mappings which are not explicitly defined by
136+
* {@linkplain org.hibernate.annotations.AnyDiscriminatorValue}.
138137
*
139-
* @since 7.0
140-
*/
141-
@Incubating
142-
public void setDiscriminatorValueStrategy(AnyDiscriminatorValueStrategy discriminatorValueStrategy) {
143-
this.discriminatorValueStrategy = discriminatorValueStrategy;
144-
}
145-
146-
/**
147-
* Set whether to use the entity's short-name for implicit discriminator value mappings
138+
* @apiNote {@code null} indicates to not allow implicit mappings.
148139
*
149140
* @since 7.0
150141
*/
151142
@Incubating
152-
public void setImplicitEntityShortName(boolean implicitEntityShortName) {
153-
this.implicitEntityShortName = implicitEntityShortName;
143+
public void setImplicitDiscriminatorValueStrategy(ImplicitDiscriminatorStrategy implicitValueStrategy) {
144+
this.implicitValueStrategy = implicitValueStrategy;
154145
}
155146

156147
@Override
@@ -175,9 +166,8 @@ public AnyType getType() throws MappingException {
175166
resolvedType = MappingHelper.anyMapping(
176167
discriminatorType,
177168
identifierType,
178-
discriminatorValueStrategy,
179-
implicitEntityShortName,
180169
metaValueToEntityNameMap,
170+
implicitValueStrategy,
181171
isLazy(),
182172
getBuildingContext()
183173
);
@@ -335,7 +325,6 @@ public void setKey(BasicValue keyDescriptor) {
335325
public static class MetaValue extends SimpleValue {
336326
private String typeName;
337327
private String columnName;
338-
private AnyDiscriminatorValueStrategy valueStrategy;
339328

340329
private final Consumer<Selectable> selectableConsumer;
341330

@@ -428,10 +417,6 @@ public boolean isValid(MappingContext mappingContext) {
428417
return columnName != null
429418
&& getType().getColumnSpan( mappingContext ) == 1;
430419
}
431-
432-
public AnyDiscriminatorValueStrategy getValueStrategy() {
433-
return valueStrategy;
434-
}
435420
}
436421

437422
public static class KeyValue extends SimpleValue {

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
import org.hibernate.boot.spi.MetadataBuildingContext;
1919
import org.hibernate.boot.spi.MetadataImplementor;
2020
import org.hibernate.internal.util.collections.CollectionHelper;
21+
import org.hibernate.metamodel.spi.ImplicitDiscriminatorStrategy;
2122
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
2223
import org.hibernate.resource.beans.spi.ManagedBean;
2324
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
2425
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
25-
import org.hibernate.type.AnyDiscriminatorValueStrategy;
2626
import org.hibernate.type.AnyType;
2727
import org.hibernate.type.CollectionType;
2828
import org.hibernate.type.CustomCollectionType;
@@ -132,9 +132,8 @@ public static AnyType anyMapping(
132132
return anyMapping(
133133
discriminatorType,
134134
identifierType,
135-
AnyDiscriminatorValueStrategy.AUTO,
136-
false,
137135
explicitValeMappings,
136+
null,
138137
lazy,
139138
buildingContext
140139
);
@@ -143,12 +142,11 @@ public static AnyType anyMapping(
143142
public static AnyType anyMapping(
144143
Type discriminatorType,
145144
Type identifierType,
146-
AnyDiscriminatorValueStrategy discriminatorValueStrategy,
147-
boolean implicitEntityShortName,
148145
Map<Object, String> explicitValeMappings,
146+
ImplicitDiscriminatorStrategy implicitValueStrategy,
149147
boolean lazy,
150148
MetadataBuildingContext buildingContext) {
151-
final MetaType metaType = new MetaType( discriminatorType, discriminatorValueStrategy, implicitEntityShortName, explicitValeMappings );
149+
final MetaType metaType = new MetaType( discriminatorType, implicitValueStrategy, explicitValeMappings );
152150
return new AnyType( buildingContext.getBootstrapContext().getTypeConfiguration(), metaType, identifierType, lazy );
153151
}
154152

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.metamodel.internal;
6+
7+
import org.hibernate.HibernateException;
8+
import org.hibernate.metamodel.mapping.EntityMappingType;
9+
import org.hibernate.metamodel.model.domain.NavigableRole;
10+
import org.hibernate.metamodel.spi.ImplicitDiscriminatorStrategy;
11+
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
12+
import org.hibernate.persister.entity.EntityPersister;
13+
14+
/**
15+
* @author Steve Ebersole
16+
*/
17+
public class FullNameImplicitDiscriminatorStrategy implements ImplicitDiscriminatorStrategy {
18+
public static final FullNameImplicitDiscriminatorStrategy FULL_NAME_STRATEGY = new FullNameImplicitDiscriminatorStrategy();
19+
20+
@Override
21+
public Object toDiscriminatorValue(EntityMappingType entityMapping, NavigableRole discriminatorRole, MappingMetamodelImplementor mappingModel) {
22+
return entityMapping.getEntityName();
23+
}
24+
25+
@Override
26+
public EntityMappingType toEntityMapping(Object discriminatorValue, NavigableRole discriminatorRole, MappingMetamodelImplementor mappingModel) {
27+
if ( discriminatorValue instanceof String assumedEntityName ) {
28+
final EntityPersister persister = mappingModel.findEntityDescriptor( assumedEntityName );
29+
30+
if ( persister != null ) {
31+
return persister;
32+
}
33+
}
34+
35+
throw new HibernateException( "Cannot interpret discriminator value (" + discriminatorRole + ") : " + discriminatorValue );
36+
}
37+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* SPDX-License-Identifier: LGPL-2.1-or-later
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.metamodel.internal;
6+
7+
import org.hibernate.HibernateException;
8+
import org.hibernate.metamodel.mapping.EntityMappingType;
9+
import org.hibernate.metamodel.model.domain.NavigableRole;
10+
import org.hibernate.metamodel.spi.ImplicitDiscriminatorStrategy;
11+
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
12+
13+
/**
14+
* @author Steve Ebersole
15+
*/
16+
public class ShortNameImplicitDiscriminatorStrategy implements ImplicitDiscriminatorStrategy {
17+
public static final ShortNameImplicitDiscriminatorStrategy SHORT_NAME_STRATEGY = new ShortNameImplicitDiscriminatorStrategy();
18+
19+
@Override
20+
public Object toDiscriminatorValue(EntityMappingType entityMapping, NavigableRole discriminatorRole, MappingMetamodelImplementor mappingModel) {
21+
return entityMapping.getImportedName();
22+
}
23+
24+
@Override
25+
public EntityMappingType toEntityMapping(Object discriminatorValue, NavigableRole discriminatorRole, MappingMetamodelImplementor mappingModel) {
26+
if ( discriminatorValue instanceof String assumedEntityName ) {
27+
final String importedName = mappingModel.getImportedName( assumedEntityName );
28+
final EntityMappingType entityMapping = mappingModel.findEntityDescriptor( importedName );
29+
if ( entityMapping != null ) {
30+
return entityMapping;
31+
}
32+
}
33+
34+
throw new HibernateException( "Cannot interpret discriminator value (" + discriminatorRole + ") : " + discriminatorValue );
35+
}
36+
}

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

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

7-
import org.hibernate.Incubating;
87
import org.hibernate.metamodel.RepresentationMode;
9-
import org.hibernate.type.AnyDiscriminatorValueStrategy;
108
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
119
import org.hibernate.type.descriptor.java.JavaType;
1210

@@ -31,9 +29,6 @@ public DiscriminatorConverter(
3129
this.relationalJavaType = relationalJavaType;
3230
}
3331

34-
@Incubating
35-
public abstract AnyDiscriminatorValueStrategy getValueStrategy();
36-
3732
public String getDiscriminatorName() {
3833
return discriminatorName;
3934
}
@@ -101,5 +96,8 @@ public String toString() {
10196

10297
public abstract void forEachValueDetail(Consumer<DiscriminatorValueDetails> consumer);
10398

99+
/**
100+
* Find and return the first DiscriminatorValueDetails which matches the given {@code handler}
101+
*/
104102
public abstract <X> X fromValueDetails(Function<DiscriminatorValueDetails,X> handler);
105103
}

0 commit comments

Comments
 (0)