6
6
*/
7
7
package org .hibernate .boot .model .process .internal ;
8
8
9
+ import java .util .Locale ;
10
+
11
+ import org .hibernate .boot .registry .classloading .spi .ClassLoaderService ;
12
+ import org .hibernate .boot .spi .BootstrapContext ;
13
+ import org .hibernate .boot .spi .MetadataBuildingContext ;
14
+ import org .hibernate .internal .util .StringHelper ;
9
15
import org .hibernate .mapping .BasicValue ;
10
- import org .hibernate .type . BasicType ;
16
+ import org .hibernate .service . ServiceRegistry ;
11
17
import org .hibernate .type .ConvertedBasicType ;
12
- import org .hibernate .type .CustomType ;
13
- import org .hibernate .type .EnumType ;
18
+ import org .hibernate .type .descriptor . converter . internal . NamedEnumValueConverter ;
19
+ import org .hibernate .type .descriptor . converter . internal . OrdinalEnumValueConverter ;
14
20
import org .hibernate .type .descriptor .converter .spi .EnumValueConverter ;
15
21
import org .hibernate .type .descriptor .java .EnumJavaType ;
16
22
import org .hibernate .type .descriptor .java .ImmutableMutabilityPlan ;
17
23
import org .hibernate .type .descriptor .java .JavaType ;
18
24
import org .hibernate .type .descriptor .java .MutabilityPlan ;
25
+ import org .hibernate .type .descriptor .java .spi .JavaTypeRegistry ;
19
26
import org .hibernate .type .descriptor .jdbc .JdbcType ;
27
+ import org .hibernate .type .descriptor .jdbc .JdbcTypeIndicators ;
28
+ import org .hibernate .type .descriptor .jdbc .spi .JdbcTypeRegistry ;
20
29
import org .hibernate .type .internal .ConvertedBasicTypeImpl ;
21
30
import org .hibernate .type .spi .TypeConfiguration ;
22
31
32
+ import jakarta .persistence .EnumType ;
33
+
34
+ import static org .hibernate .type .SqlTypes .SMALLINT ;
35
+ import static org .hibernate .type .SqlTypes .TINYINT ;
36
+
23
37
/**
24
38
* Resolution for {@linkplain Enum enum} mappings
25
39
*
26
40
* @author Steve Ebersole
27
41
*/
28
42
public class EnumeratedValueResolution <E extends Enum <E >,R > implements BasicValue .Resolution <E > {
29
- private final EnumValueConverter < E , R > valueConverter ;
43
+ public static final String PREFIX = "enum::" ;
30
44
45
+ private final EnumValueConverter <E ,R > valueConverter ;
31
46
private final ConvertedBasicType <E > jdbcMapping ;
32
- private final CustomType <E > legacyTypeResolution ;
33
47
34
48
public EnumeratedValueResolution (
35
49
JdbcType jdbcType ,
36
50
EnumValueConverter <E , R > valueConverter ,
37
- TypeConfiguration typeConfiguration ) {
51
+ MetadataBuildingContext context ) {
38
52
this .valueConverter = valueConverter ;
39
53
40
- final EnumJavaType <E > domainJavaType = valueConverter .getDomainJavaType ();
41
- this .jdbcMapping = new ConvertedBasicTypeImpl <>(
42
- domainJavaType .getJavaTypeClass ().getName (),
43
- jdbcType ,
44
- valueConverter
45
- );
46
- this .legacyTypeResolution = new CustomType <>(
47
- new EnumType <>( domainJavaType .getJavaTypeClass (), valueConverter , typeConfiguration ),
48
- typeConfiguration
54
+ final String externalizableName = createName ( valueConverter );
55
+ this .jdbcMapping = new ConvertedBasicTypeImpl <>( externalizableName , jdbcType , valueConverter );
56
+
57
+ context .getMetadataCollector ().registerEnumMapping ( jdbcMapping );
58
+ }
59
+
60
+ private String createName (EnumValueConverter <E , R > valueConverter ) {
61
+ return String .format (
62
+ Locale .ROOT ,
63
+ PREFIX + "%s::%s" ,
64
+ valueConverter .getDomainJavaType ().getJavaType ().getName (),
65
+ enumStyle ( valueConverter ).name ()
49
66
);
50
67
}
51
68
69
+ private static EnumType enumStyle (EnumValueConverter <?,?> valueConverter ) {
70
+ if ( valueConverter instanceof NamedEnumValueConverter ) {
71
+ return EnumType .STRING ;
72
+ }
73
+ else if ( valueConverter instanceof OrdinalEnumValueConverter ) {
74
+ return EnumType .ORDINAL ;
75
+ }
76
+ throw new UnsupportedOperationException ();
77
+ }
78
+
52
79
@ Override
53
80
public ConvertedBasicType <E > getJdbcMapping () {
54
81
return jdbcMapping ;
55
82
}
56
83
57
84
@ Override
58
- public BasicType getLegacyResolvedBasicType () {
59
- return legacyTypeResolution ;
85
+ public ConvertedBasicType < E > getLegacyResolvedBasicType () {
86
+ return jdbcMapping ;
60
87
}
61
88
62
89
@ Override
@@ -83,4 +110,60 @@ public EnumValueConverter<E,R> getValueConverter() {
83
110
public MutabilityPlan <E > getMutabilityPlan () {
84
111
return ImmutableMutabilityPlan .instance ();
85
112
}
113
+
114
+ public static <E extends Enum <E >> EnumeratedValueResolution <E ,?> fromName (
115
+ String name ,
116
+ JdbcTypeIndicators jdbcTypeIndicators ,
117
+ MetadataBuildingContext context ) {
118
+ assert name != null ;
119
+ assert name .startsWith ( PREFIX );
120
+
121
+ final String [] parts = StringHelper .split ( "::" , name );
122
+ assert parts .length == 3 ;
123
+ assert "enum" .equals ( parts [0 ] );
124
+
125
+ final TypeConfiguration typeConfiguration = context .getBootstrapContext ().getTypeConfiguration ();
126
+ final JavaTypeRegistry javaTypeRegistry = typeConfiguration .getJavaTypeRegistry ();
127
+ final JdbcTypeRegistry jdbcTypeRegistry = typeConfiguration .getJdbcTypeRegistry ();
128
+
129
+ final Class <E > enumClass = resolveEnumClass ( parts [1 ], context .getBootstrapContext () );
130
+ final jakarta .persistence .EnumType style = jakarta .persistence .EnumType .valueOf ( parts [ 2 ] );
131
+
132
+ //noinspection unchecked,rawtypes
133
+ final EnumJavaType <E > enumJavaType = (EnumJavaType ) javaTypeRegistry .getDescriptor ( enumClass );
134
+ final JdbcType jdbcType ;
135
+ final EnumValueConverter <E ,?> converter ;
136
+
137
+ if ( style == EnumType .ORDINAL ) {
138
+ jdbcType = jdbcTypeRegistry .getDescriptor ( enumJavaType .hasManyValues () ? SMALLINT : TINYINT );
139
+
140
+ final JavaType <Integer > jdbcJavaType = javaTypeRegistry .getDescriptor ( Integer .class );
141
+ converter = new OrdinalEnumValueConverter <>( enumJavaType , jdbcType , jdbcJavaType );
142
+ }
143
+ else if ( style == EnumType .STRING ) {
144
+ //noinspection rawtypes
145
+ final JavaType jdbcJavaType ;
146
+ if ( jdbcTypeIndicators .getColumnLength () == 1 ) {
147
+ jdbcJavaType = javaTypeRegistry .getDescriptor ( Character .class );
148
+ }
149
+ else {
150
+ jdbcJavaType = javaTypeRegistry .getDescriptor ( String .class );
151
+ }
152
+ jdbcType = jdbcJavaType .getRecommendedJdbcType ( jdbcTypeIndicators );
153
+ //noinspection unchecked,rawtypes
154
+ converter = new NamedEnumValueConverter <>( enumJavaType , jdbcType , jdbcJavaType );
155
+ }
156
+ else {
157
+ throw new IllegalArgumentException ( );
158
+ }
159
+
160
+ return new EnumeratedValueResolution <>( jdbcType , converter , context );
161
+ }
162
+
163
+ private static <E extends Enum <E >> Class <E > resolveEnumClass (String enumClassName , BootstrapContext bootstrapContext ) {
164
+ final ServiceRegistry serviceRegistry = bootstrapContext .getServiceRegistry ();
165
+ final ClassLoaderService classLoaderService = serviceRegistry .getService ( ClassLoaderService .class );
166
+
167
+ return classLoaderService .classForName ( enumClassName );
168
+ }
86
169
}
0 commit comments