Skip to content

Commit 5b2e440

Browse files
committed
HHH-19247 Add ordinal() also to Type contributions to be able to influence the order in which serviceloaded custom types are registered
1 parent 4438ada commit 5b2e440

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/TypeContributor.java

+17
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,21 @@ public interface TypeContributor {
4141
* @param serviceRegistry The service registry
4242
*/
4343
void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry);
44+
45+
/**
46+
* Determines order in which the contributions will be applied
47+
* (lowest ordinal first).
48+
* <p>
49+
* The range 0-500 is reserved for Hibernate, range 500-1000 for libraries and
50+
* 1000-Integer.MAX_VALUE for user-defined TypeContributors.
51+
* <p>
52+
* Contributions from higher precedence contributors (higher numbers) effectively override
53+
* contributions from lower precedence. E.g. if a contributor with precedence 2000 contributes
54+
* some type, that will override Hibernate's standard type of that name.
55+
*
56+
* @return the ordinal for this TypeContributor
57+
*/
58+
default int ordinal(){
59+
return 1000;
60+
}
4461
}

hibernate-core/src/main/java/org/hibernate/boot/model/process/spi/MetadataBuildingProcess.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787

8888
import jakarta.persistence.AttributeConverter;
8989

90+
import static java.util.Comparator.comparingInt;
9091
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForArray;
9192
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForDuration;
9293
import static org.hibernate.internal.util.config.ConfigurationHelper.getPreferredSqlTypeCodeForInstant;
@@ -642,7 +643,7 @@ public void contributeType(CompositeUserType<?> type) {
642643
final JdbcType dialectArrayDescriptor = jdbcTypeRegistry.findDescriptor( SqlTypes.ARRAY );
643644

644645
// add TypeContributor contributed types.
645-
for ( TypeContributor contributor : classLoaderService.loadJavaServices( TypeContributor.class ) ) {
646+
for ( TypeContributor contributor : sortedTypeContributors( classLoaderService ) ) {
646647
contributor.contribute( typeContributions, options.getServiceRegistry() );
647648
}
648649

@@ -749,6 +750,17 @@ public void contributeType(CompositeUserType<?> type) {
749750
}
750751
}
751752

753+
private static List<TypeContributor> sortedTypeContributors(
754+
ClassLoaderService classLoaderService) {
755+
Collection<TypeContributor> typeContributors = classLoaderService.loadJavaServices( TypeContributor.class );
756+
List<TypeContributor> contributors = new ArrayList<>( typeContributors );
757+
contributors.sort(
758+
comparingInt( TypeContributor::ordinal )
759+
.thenComparing( a -> a.getClass().getCanonicalName() )
760+
);
761+
return contributors;
762+
}
763+
752764
private static void adaptToPreferredSqlTypeCode(
753765
JdbcTypeRegistry jdbcTypeRegistry,
754766
JdbcType dialectUuidDescriptor,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package org.hibernate.orm.test.type.contributor.usertype;
2+
3+
import org.hibernate.boot.model.TypeContributions;
4+
import org.hibernate.boot.model.TypeContributor;
5+
import org.hibernate.service.ServiceRegistry;
6+
7+
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry;
8+
import org.hibernate.testing.orm.junit.DomainModel;
9+
import org.hibernate.testing.orm.junit.Jira;
10+
import org.hibernate.testing.orm.junit.SessionFactory;
11+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
12+
13+
import org.hibernate.type.descriptor.jdbc.VarcharJdbcType;
14+
import org.hibernate.type.spi.TypeConfiguration;
15+
16+
import org.junit.jupiter.api.Assertions;
17+
import org.junit.jupiter.api.Test;
18+
19+
/**
20+
* Test to assert that service loaded types are processed in ascending ordinal order
21+
*
22+
* @author Steven Barendregt
23+
*/
24+
@DomainModel
25+
@SessionFactory
26+
@BootstrapServiceRegistry(
27+
javaServices = {
28+
@BootstrapServiceRegistry.JavaService(role = TypeContributor.class, impl = TypeContributionOrdinalTest.HigherOrdinalServiceLoadedVarcharTypeContributor.class),
29+
@BootstrapServiceRegistry.JavaService(role = TypeContributor.class, impl = TypeContributionOrdinalTest.ServiceLoadedVarcharTypeContributor.class)
30+
}
31+
)
32+
public class TypeContributionOrdinalTest {
33+
34+
@Test
35+
@Jira(value = "https://hibernate.atlassian.net/issues/HHH-19247")
36+
public void testHigherOrdinalServiceLoadedCustomUserTypeTakesPrecedence(SessionFactoryScope scope) {
37+
final TypeConfiguration typeConfigurations = scope.getSessionFactory()
38+
.getMappingMetamodel()
39+
.getTypeConfiguration();
40+
Assertions.assertInstanceOf(
41+
HigherOrdinalServiceLoadedVarcharTypeContributor.HigherOrdinalExtendedVarcharJdbcType.class,
42+
typeConfigurations.getJdbcTypeRegistry().findDescriptor( 12 )
43+
);
44+
}
45+
46+
public static class ServiceLoadedVarcharTypeContributor implements TypeContributor {
47+
48+
@Override
49+
public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
50+
typeContributions.contributeJdbcType( ExtendedVarcharJdbcType.INSTANCE );
51+
}
52+
53+
public static class ExtendedVarcharJdbcType extends VarcharJdbcType {
54+
55+
public static final ExtendedVarcharJdbcType INSTANCE = new ExtendedVarcharJdbcType();
56+
}
57+
58+
}
59+
60+
public static class HigherOrdinalServiceLoadedVarcharTypeContributor implements TypeContributor {
61+
62+
@Override
63+
public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
64+
typeContributions.contributeJdbcType( HigherOrdinalExtendedVarcharJdbcType.INSTANCE );
65+
}
66+
67+
@Override
68+
public int ordinal() {
69+
return 2000;
70+
}
71+
72+
public static class HigherOrdinalExtendedVarcharJdbcType extends VarcharJdbcType {
73+
74+
public static final HigherOrdinalExtendedVarcharJdbcType INSTANCE = new HigherOrdinalExtendedVarcharJdbcType();
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)