diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/type/PostgresIntervalSecondTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/type/PostgresIntervalSecondTest.java new file mode 100644 index 0000000000..630405c8b4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/type/PostgresIntervalSecondTest.java @@ -0,0 +1,95 @@ +package org.hibernate.orm.test.type; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; + +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.PostgreSQLDialect; +import org.hibernate.dialect.PostgreSQLIntervalSecondJdbcType; +import org.hibernate.metamodel.spi.MappingMetamodelImplementor; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.type.SqlTypes; +import org.hibernate.type.descriptor.jdbc.JdbcType; +import org.hibernate.type.descriptor.jdbc.NumericJdbcType; +import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.RequiresDialect; +import org.hibernate.testing.orm.junit.ServiceRegistry; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.Setting; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +/** + * Test to see if using `@org.hibernate.annotations.JdbcTypeCode` or `@org.hibernate.annotations.JdbcType` + * will override a default JdbcType set by a {@link AvailableSettings#PREFERRED_DURATION_JDBC_TYPE config property}. + */ +@SessionFactory +@DomainModel(annotatedClasses = { PostgresIntervalSecondTest.EntityWithIntervalSecondDuration.class }) +@ServiceRegistry(settings = @Setting(name = AvailableSettings.PREFERRED_DURATION_JDBC_TYPE, value = "NUMERIC")) +@RequiresDialect(PostgreSQLDialect.class) +public class PostgresIntervalSecondTest { + + @Test + public void verifyMappings(SessionFactoryScope scope) { + final MappingMetamodelImplementor mappingMetamodel = scope.getSessionFactory() + .getRuntimeMetamodels() + .getMappingMetamodel(); + final EntityPersister entityDescriptor = mappingMetamodel.findEntityDescriptor( + PostgresIntervalSecondTest.EntityWithIntervalSecondDuration.class ); + final JdbcTypeRegistry jdbcTypeRegistry = mappingMetamodel.getTypeConfiguration().getJdbcTypeRegistry(); + + + final JdbcType intervalType = jdbcTypeRegistry.getDescriptor( SqlTypes.INTERVAL_SECOND ); + + // default interval type set by a config property and should be `NUMERIC` + assertThat( intervalType ).isEqualTo( NumericJdbcType.INSTANCE ); + + // a simple duration field with no overrides - so should be using a default JdbcType + assertThat( entityDescriptor.findAttributeMapping( "duration" ) + .getSingleJdbcMapping().getJdbcType() ) + .isEqualTo( intervalType ); + + // a field that is using a @JdbcType annotation to override the JdbcType. Hence, the used JdbcType must match the one + // set by the annotation. + assertThat( entityDescriptor.findAttributeMapping( "durationJdbcType" ) + .getSingleJdbcMapping().getJdbcType() ) + .isNotEqualTo( intervalType ) + .isOfAnyClassIn( PostgreSQLIntervalSecondJdbcType.class ); + + // a field that is using a @JdbcTypeCode annotation to override the JdbcType. Hence, the used JdbcType must match the one + // set by the annotation. + assertThat( entityDescriptor.findAttributeMapping( "durationJdbcTypeCode" ) + .getSingleJdbcMapping().getJdbcType() ) + .isNotEqualTo( intervalType ) + .isOfAnyClassIn( PostgreSQLIntervalSecondJdbcType.class ); + } + + @Entity(name = "EntityWithIntervalSecondDuration") + @Table(name = "EntityWithIntervalSecondDuration") + public static class EntityWithIntervalSecondDuration { + @Id + private Integer id; + + private Duration duration; + + @Column(precision = 10, scale = 6) + @JdbcTypeCode(SqlTypes.INTERVAL_SECOND) + private Duration durationJdbcTypeCode; + + @Column(precision = 10, scale = 6) + @org.hibernate.annotations.JdbcType(PostgreSQLIntervalSecondJdbcType.class) + private Duration durationJdbcType; + + public EntityWithIntervalSecondDuration() { + } + } +}