From 7a6cef5838a47ac95601e5c50879ead2dd732c52 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Thu, 9 Dec 2021 00:51:40 -0600 Subject: [PATCH] Miscellaneous - Finished DialectVersion - User Guide tidying - User Guide section on AttributeBinder --- .../userguide/appendices/Annotations.adoc | 79 +++++++++++++++---- .../chapters/domain/DomainModel.adoc | 1 + .../userguide/chapters/domain/access.adoc | 10 +-- .../chapters/domain/customizing.adoc | 18 +++++ .../EmbeddedIdDatabaseGeneratedValueTest.java | 2 +- .../community/dialect/FirebirdDialect.java | 4 +- .../dialect/FirebirdSqlAstTranslator.java | 6 +- .../community/dialect/Informix10Dialect.java | 4 +- .../dialect/InformixSqlAstTranslator.java | 4 +- .../community/dialect/Ingres10Dialect.java | 4 +- .../community/dialect/Ingres9Dialect.java | 4 +- .../dialect/IngresSqlAstTranslator.java | 4 +- .../dialect/MaxDBSqlAstTranslator.java | 2 +- .../dialect/SQLiteSqlAstTranslator.java | 4 +- .../dialect/SybaseAnywhereDialect.java | 25 +++--- .../SybaseAnywhereSqlAstTranslator.java | 10 +-- .../community/dialect/Teradata14Dialect.java | 4 +- .../dialect/TeradataSqlAstTranslator.java | 2 +- .../cfg/annotations/BasicValueBinder.java | 23 ++++-- .../SimpleAttributeBinderTests.java | 48 +++++++++++ .../test/mapping/attributebinder/System.java | 52 ++++++++++++ .../test/mapping/attributebinder/YesNo.java | 29 +++++++ .../mapping/attributebinder/YesNoBinder.java | 56 +++++++++++++ .../mapping/attributebinder/package-info.java | 12 +++ .../ValidityAuditStrategyRevEndTsTest.java | 4 +- .../dialect/postgis/PostgisPG10Dialect.java | 3 +- .../dialect/postgis/PostgisPG93Dialect.java | 7 +- .../dialect/postgis/PostgisPG94Dialect.java | 7 +- .../dialect/postgis/PostgisPG95Dialect.java | 4 - .../spatial/testing/TestSupportFactories.java | 2 +- 30 files changed, 358 insertions(+), 76 deletions(-) create mode 100644 documentation/src/main/asciidoc/userguide/chapters/domain/customizing.adoc create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/SimpleAttributeBinderTests.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/System.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/YesNo.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/YesNoBinder.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/package-info.java diff --git a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc index 802b64a36b..b51360947f 100644 --- a/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc +++ b/documentation/src/main/asciidoc/userguide/appendices/Annotations.adoc @@ -94,7 +94,7 @@ See the <> section for more info. @@ -624,22 +624,68 @@ See the <> section for more info. -[[annotations-hibernate-anymetadef]] -==== `@AnyMetaDef` +[[annotations-hibernate-anydiscriminator]] +==== `@AnyDiscriminator` -The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyMetaDef.html[`@AnyMetaDef`] annotation is used to provide metadata about an `@Any` or `@ManyToAny` mapping. +The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyDiscriminator.html[`@AnyDiscriminator`] +annotation is used to provide details about the discriminator portion of an `@Any` or `@ManyToAny` mapping. See the <> section for more info. -[[annotations-hibernate-anymetadefs]] -==== `@AnyMetaDefs` +[[annotations-hibernate-anydiscriminatorvalue]] +==== `@AnyDiscriminatorValue` + +The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyDiscriminatorValue.html[`@AnyDiscriminatorValue`] +annotation maps a single discriminator value to its corresponding entity + +See the <> section for more info. + +[[annotations-hibernate-anydiscriminatorvalues]] +==== `@AnyDiscriminatorValues` + +The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyDiscriminatorValues.html[`@AnyDiscriminatorValues`] +annotation groups multiple <> annotations. + +See the <> section for more info. + +[[annotations-hibernate-anykeyjavaclass]] +==== `@AnyKeyJavaClass` + +The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyKeyJavaClass.html[`@AnyKeyJavaClass`] +annotation specifies the Java Class to use for the foreign-key of an ANY mapping + +See the <> section for more info. + +[[annotations-hibernate-anykeyjavatype]] +==== `@AnyKeyJavaType` + +The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyKeyJavaType.html[`@AnyKeyJavaType`] +annotation specifies a specific JavaType descriptor to use for the foreign-key of an ANY mapping + +See the <> section for more info. + + +[[annotations-hibernate-anykeyjdbctype]] +==== `@AnyKeyJdbcType` + +The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyKeyJdbcType.html[`@AnyKeyJdbcType`] +annotation specifies a specific JdbcType descriptor to use for the foreign-key of an ANY mapping + +See the <> section for more info. + +[[annotations-hibernate-anykeyjdbctypecode]] +==== `@AnyKeyJdbcTypeCode` + +The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyKeyJdbcTypeCode.html[`@AnyKeyJdbcTypeCode`] +annotation specifies a "type code" indicating which JdbcType descriptor to use for the foreign-key of an ANY mapping + +See the <> section for more info. -The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AnyMetaDefs.html[`@AnyMetaDefs`] annotation is used to group multiple <> annotations. [[annotations-hibernate-attributeaccessor]] ==== `@AttributeAccessor` @@ -651,6 +697,16 @@ For property/field access type, the Jakarta Persistence <> annotation. + +[[annotations-hibernate-attributebindertype]] +==== `@AttributeBinderType` + +The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AttributeBinderType.html[`@AttributeBinderType`] +annotation is a meta-annotation used to annotate a custom annotation type used to drive customized model binding. + +See <>. + + [[annotations-hibernate-batchsize]] ==== `@BatchSize` @@ -1341,11 +1397,6 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern See the <> section for more info. -[[annotations-hibernate-attributebindertype]] -==== `@AttributeBinderType` - -The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/AttributeBinderType.html[`@AttributeBinderType`] annotation is used to specify that the current annotation type should is used to drive -customized model binding. [[annotations-hibernate-tenantid]] ==== `@TenantId` diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/DomainModel.adoc b/documentation/src/main/asciidoc/userguide/chapters/domain/DomainModel.adoc index 6c142b60f4..f23009dbde 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/domain/DomainModel.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/DomainModel.adoc @@ -35,3 +35,4 @@ include::natural_id.adoc[] include::dynamic_model.adoc[] include::inheritance.adoc[] include::immutability.adoc[] +include::customizing.adoc[] diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/access.adoc b/documentation/src/main/asciidoc/userguide/chapters/domain/access.adoc index 020d557f10..263155789f 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/domain/access.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/access.adoc @@ -1,5 +1,5 @@ [[access]] -==== Access strategies +=== Access strategies :sourcedir: ../../../../../test/java/org/hibernate/userguide/mapping/access :extrasdir: extras @@ -18,7 +18,7 @@ https://docs.oracle.com/javase/8/docs/api/java/beans/Introspector.html#decapital Embeddable types inherit the access strategy from their parent entities. [[field-based-access]] -===== Field-based access +==== Field-based access [[access-field-mapping-example]] .Field-based access @@ -42,7 +42,7 @@ With field-based access, we can simply omit the getter and the setter for this v ==== [[property-based-access]] -===== Property-based access +==== Property-based access [[access-property-mapping-example]] .Property-based access @@ -56,7 +56,7 @@ include::{sourcedir}/PropertyAccessTest.java[tag=access-property-mapping-example When using property-based access, Hibernate uses the accessors for both reading and writing the entity state. Every other method that will be added to the entity (e.g. helper methods for synchronizing both ends of a bidirectional one-to-many association) will have to be marked with the `@Transient` annotation. -===== Overriding the default access strategy +==== Overriding the default access strategy The default access strategy mechanism can be overridden with the Jakarta Persistence `@Access` annotation. In the following example, the `@Version` attribute is accessed by its field and not by its getter, like the rest of entity attributes. @@ -71,7 +71,7 @@ include::{sourcedir}/PropertyAccessOverrideTest.java[tag=access-property-overrid ==== [[access-embeddable-types]] -===== Embeddable types and access strategy +==== Embeddable types and access strategy Because embeddables are managed by their owning entities, the access strategy is therefore inherited from the entity too. This applies to both simple embeddable types as well as for collection of embeddables. diff --git a/documentation/src/main/asciidoc/userguide/chapters/domain/customizing.adoc b/documentation/src/main/asciidoc/userguide/chapters/domain/customizing.adoc new file mode 100644 index 0000000000..414ff06733 --- /dev/null +++ b/documentation/src/main/asciidoc/userguide/chapters/domain/customizing.adoc @@ -0,0 +1,18 @@ +[[domain-customizing]] +=== Customizing the domain model +:rootProjectDir: ../../../../../../.. +:coreProjectDir: {rootProjectDir}/hibernate-core +:attributeBinderTestDir: {coreProjectDir}/src/test/java/org/hibernate/orm/test/mapping/attributebinder +:extrasdir: extras + + +[[domain-customizing-example]] +.AttributeBinder example +==== +[source,java] +---- +include::{attributeBinderTestDir}/YesNo.java[tag=attribute-binder-example, indent=0] + +include::{attributeBinderTestDir}/YesNoBinder.java[tag=attribute-binder-example, indent=0] +---- +==== \ No newline at end of file diff --git a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/composite/EmbeddedIdDatabaseGeneratedValueTest.java b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/composite/EmbeddedIdDatabaseGeneratedValueTest.java index ce7f9ed6ce..eba8812596 100644 --- a/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/composite/EmbeddedIdDatabaseGeneratedValueTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/mapping/identifier/composite/EmbeddedIdDatabaseGeneratedValueTest.java @@ -25,7 +25,7 @@ import static org.junit.Assert.assertEquals; * @author Vlad Mihalcea */ // On H2 1.4.199+ CURRENT_TIMESTAMP returns a timestamp with timezone -@RequiresDialect(value = H2Dialect.class, version = 104199) +@RequiresDialect(value = H2Dialect.class, majorVersion = 1, minorVersion = 4, microVersion = 199) @DomainModel(annotatedClasses = Event.class) @SessionFactory public class EmbeddedIdDatabaseGeneratedValueTest { diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java index 107f4d2487..b56725c6cc 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java @@ -489,7 +489,7 @@ public class FirebirdDialect extends Dialect { @Override public int getMaxIdentifierLength() { - return getVersion() < 400 ? 31 : 63; + return getVersion().isBefore( 4 ) ? 31 : 63; } public IdentifierHelper buildIdentifierHelper( @@ -889,7 +889,7 @@ public class FirebirdDialect extends Dialect { @Override public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(EntityMappingType entityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) { - return getVersion() < 210 + return getVersion().isBefore( 2, 1 ) ? super.getFallbackSqmInsertStrategy( entityDescriptor, runtimeModelCreationContext ) : new GlobalTemporaryTableInsertStrategy( TemporaryTable.createEntityTable( diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdSqlAstTranslator.java index 191a649b19..0b0c26ffa7 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdSqlAstTranslator.java @@ -53,7 +53,7 @@ public class FirebirdSqlAstTranslator extends AbstractS @Override public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) { - if ( getDialect().getVersion() >= 300 ) { + if ( getDialect().getVersion().isSameOrAfter( 3 ) ) { booleanExpressionPredicate.getExpression().accept( this ); } else { @@ -71,7 +71,7 @@ public class FirebirdSqlAstTranslator extends AbstractS // Before 3.0 there was also no support for window functions // Check if current query part is already row numbering to avoid infinite recursion return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart - && getDialect().getVersion() >= 300 && !isRowsOnlyFetchClauseType( queryPart ); + && getDialect().getVersion().isSameOrAfter( 3 ) && !isRowsOnlyFetchClauseType( queryPart ); } @Override @@ -201,7 +201,7 @@ public class FirebirdSqlAstTranslator extends AbstractS } private boolean supportsOffsetFetchClause() { - return getDialect().getVersion() >= 300; + return getDialect().getVersion().isSameOrAfter( 3 ); } @Override diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Informix10Dialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Informix10Dialect.java index 778d5db14a..275b67ec6f 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Informix10Dialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Informix10Dialect.java @@ -6,6 +6,8 @@ */ package org.hibernate.community.dialect; +import org.hibernate.dialect.DatabaseVersion; + /** * Dialect for Informix 10 * @@ -15,7 +17,7 @@ package org.hibernate.community.dialect; public class Informix10Dialect extends InformixDialect { public Informix10Dialect() { - super(10); + super( DatabaseVersion.make( 10 ) ); } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java index d3dde81156..5fb2f1b982 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java @@ -154,10 +154,10 @@ public class InformixSqlAstTranslator extends AbstractS } private boolean supportsParameterOffsetFetchExpression() { - return getDialect().getVersion() >= 11; + return getDialect().getVersion().isSameOrAfter( 11 ); } private boolean supportsSkipFirstClause() { - return getDialect().getVersion() >= 11; + return getDialect().getVersion().isSameOrAfter( 11 ); } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Ingres10Dialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Ingres10Dialect.java index bdf2873fc9..7cfacde8d1 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Ingres10Dialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Ingres10Dialect.java @@ -6,6 +6,8 @@ */ package org.hibernate.community.dialect; +import org.hibernate.dialect.DatabaseVersion; + /** * A SQL dialect for Ingres 10 and later versions. *

@@ -23,7 +25,7 @@ package org.hibernate.community.dialect; public class Ingres10Dialect extends IngresDialect { public Ingres10Dialect() { - super(1000); + super( DatabaseVersion.make( 10 ) ); } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Ingres9Dialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Ingres9Dialect.java index b0dc52ce30..f55da63f94 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Ingres9Dialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Ingres9Dialect.java @@ -6,6 +6,8 @@ */ package org.hibernate.community.dialect; +import org.hibernate.dialect.DatabaseVersion; + /** * A SQL dialect for Ingres 9.3 and later versions. *

@@ -29,7 +31,7 @@ package org.hibernate.community.dialect; public class Ingres9Dialect extends IngresDialect { public Ingres9Dialect() { - super(930); + super( DatabaseVersion.make( 9, 3 ) ); } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java index 424f4430cc..7200cc374e 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java @@ -165,11 +165,11 @@ public class IngresSqlAstTranslator extends AbstractSql } private boolean supportsParameterOffsetFetchExpression() { - return getDialect().getVersion() >= 930; + return getDialect().getVersion().isSameOrAfter( 9, 3 ); } private boolean supportsOffsetFetchClause() { - return getDialect().getVersion() >= 930; + return getDialect().getVersion().isSameOrAfter( 9, 3 ); } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBSqlAstTranslator.java index 47f6ced982..859ee78e61 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBSqlAstTranslator.java @@ -64,7 +64,7 @@ public class MaxDBSqlAstTranslator extends AbstractSqlA @Override protected void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression, boolean inSelect) { // Couldn't find documentation for older versions, but 7.7 supports ANSI style case expressions - if ( getDialect().getVersion() < 770 ) { + if ( getDialect().getVersion().isBefore( 7, 7 ) ) { visitDecodeCaseSearchedExpression( caseSearchedExpression ); } else { diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteSqlAstTranslator.java index 4d294c0304..f8ddd4affe 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteSqlAstTranslator.java @@ -48,7 +48,7 @@ public class SQLiteSqlAstTranslator extends AbstractSql @Override protected void renderMaterializationHint(CteMaterialization materialization) { - if ( getDialect().getVersion() >= 335 ) { + if ( getDialect().getVersion().isSameOrAfter( 3, 3, 5 ) ) { if ( materialization == CteMaterialization.NOT_MATERIALIZED ) { appendSql( "not " ); } @@ -58,7 +58,7 @@ public class SQLiteSqlAstTranslator extends AbstractSql @Override public boolean supportsFilterClause() { - return getDialect().getVersion() >= 330; + return getDialect().getVersion().isSameOrAfter( 3, 3 ); } @Override diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java index 01cfc6f8a6..a430e8f6d0 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java @@ -7,12 +7,16 @@ package org.hibernate.community.dialect; +import java.sql.Types; +import java.util.Map; + import org.hibernate.LockOptions; +import org.hibernate.community.dialect.identity.SybaseAnywhereIdentityColumnSupport; +import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.RowLockStrategy; import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.TimeZoneSupport; import org.hibernate.dialect.identity.IdentityColumnSupport; -import org.hibernate.community.dialect.identity.SybaseAnywhereIdentityColumnSupport; import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.TopLimitHandler; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; @@ -24,9 +28,6 @@ import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory; import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.exec.spi.JdbcOperation; -import java.sql.Types; -import java.util.Map; - /** * SQL Dialect for Sybase Anywhere * (Tested on ASA 8.x) @@ -34,18 +35,18 @@ import java.util.Map; public class SybaseAnywhereDialect extends SybaseDialect { public SybaseAnywhereDialect() { - this( 800, false ); + this( DatabaseVersion.make( 8 ), false ); } public SybaseAnywhereDialect(DialectResolutionInfo info){ this( - info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10, + info, info.getDriverName() != null && info.getDriverName().contains( "jTDS" ) ); registerKeywords( info ); } - public SybaseAnywhereDialect(int version, boolean jtdsDriver) { + public SybaseAnywhereDialect(DatabaseVersion version, boolean jtdsDriver) { super( version, jtdsDriver ); registerColumnType( Types.BIGINT, "bigint" ); @@ -132,30 +133,30 @@ public class SybaseAnywhereDialect extends SybaseDialect { @Override public RowLockStrategy getWriteRowLockStrategy() { - return getVersion() >= 1000 ? RowLockStrategy.COLUMN : RowLockStrategy.TABLE; + return getVersion().isSameOrAfter( 10 ) ? RowLockStrategy.COLUMN : RowLockStrategy.TABLE; } @Override public String getForUpdateString() { - return getVersion() < 1000 ? "" : " for update"; + return getVersion().isBefore( 10 ) ? "" : " for update"; } @Override public String getForUpdateString(String aliases) { - return getVersion() < 1000 + return getVersion().isBefore( 10 ) ? "" : getForUpdateString() + " of " + aliases; } @Override public String appendLockHint(LockOptions mode, String tableName) { - return getVersion() < 1000 ? super.appendLockHint( mode, tableName ) : tableName; + return getVersion().isBefore( 10 ) ? super.appendLockHint( mode, tableName ) : tableName; } @Override @SuppressWarnings("deprecation") public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) { - return getVersion() < 1000 + return getVersion().isBefore( 10 ) ? super.applyLocksToSql( sql, aliasedLockOptions, keyColumnNames ) : sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString(); } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereSqlAstTranslator.java index 0c0e949c34..3d95f89895 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereSqlAstTranslator.java @@ -95,7 +95,7 @@ public class SybaseAnywhereSqlAstTranslator extends Abs @Override protected boolean renderTableReference(TableReference tableReference, LockMode lockMode) { super.renderTableReference( tableReference, lockMode ); - if ( getDialect().getVersion() < 1000 ) { + if ( getDialect().getVersion().isBefore( 10 ) ) { if ( LockMode.READ.lessThan( lockMode ) ) { appendSql( " holdlock" ); } @@ -106,7 +106,7 @@ public class SybaseAnywhereSqlAstTranslator extends Abs @Override protected void renderForUpdateClause(QuerySpec querySpec, ForUpdateClause forUpdateClause) { - if ( getDialect().getVersion() < 1000 ) { + if ( getDialect().getVersion().isBefore( 10 ) ) { return; } super.renderForUpdateClause( querySpec, forUpdateClause ); @@ -114,7 +114,7 @@ public class SybaseAnywhereSqlAstTranslator extends Abs @Override protected boolean needsRowsToSkip() { - return getDialect().getVersion() < 900; + return getDialect().getVersion().isBefore( 9 ); } @Override @@ -127,7 +127,7 @@ public class SybaseAnywhereSqlAstTranslator extends Abs @Override protected void visitSqlSelections(SelectClause selectClause) { - if ( getDialect().getVersion() < 900 ) { + if ( getDialect().getVersion().isBefore( 9 ) ) { renderTopClause( (QuerySpec) getQueryPartStack().getCurrent(), true, true ); } else { @@ -151,7 +151,7 @@ public class SybaseAnywhereSqlAstTranslator extends Abs @Override public void visitOffsetFetchClause(QueryPart queryPart) { // Sybase Anywhere only supports the TOP clause - if ( getDialect().getVersion() < 900 && !queryPart.isRoot() + if ( getDialect().getVersion().isBefore( 9 ) && !queryPart.isRoot() && useOffsetFetchClause( queryPart ) && queryPart.getOffsetClauseExpression() != null ) { throw new IllegalArgumentException( "Can't emulate offset clause in subquery" ); } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Teradata14Dialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Teradata14Dialect.java index 1c8344789a..2029ef8538 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Teradata14Dialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/Teradata14Dialect.java @@ -6,6 +6,8 @@ */ package org.hibernate.community.dialect; +import org.hibernate.dialect.DatabaseVersion; + /** * A dialect for the Teradata 14 * @@ -15,7 +17,7 @@ package org.hibernate.community.dialect; public class Teradata14Dialect extends TeradataDialect { public Teradata14Dialect() { - super(14); + super( DatabaseVersion.make( 14 ) ); } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataSqlAstTranslator.java index bdfb533b72..e6dc32531f 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataSqlAstTranslator.java @@ -36,7 +36,7 @@ public class TeradataSqlAstTranslator extends AbstractS @Override public void visitQuerySpec(QuerySpec querySpec) { - if ( querySpec.isRoot() && getDialect().getVersion() >= 14 ) { + if ( querySpec.isRoot() && getDialect().getVersion().isSameOrAfter( 14 ) ) { final ForUpdateClause forUpdateClause = new ForUpdateClause(); forUpdateClause.merge( getLockOptions() ); super.renderForUpdateClause( querySpec, forUpdateClause ); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java index 1caa25392c..6b50b9a514 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java @@ -1312,12 +1312,25 @@ public class BasicValueBinder implements JdbcTypeDescriptorIndicators { basicValue.setTypeParameters( (Map) parameters ); } - basicValue.setJpaAttributeConverterDescriptor( converterDescriptor ); + if ( converterDescriptor != null ) { + basicValue.setJpaAttributeConverterDescriptor( converterDescriptor ); + } - basicValue.setImplicitJavaTypeAccess( implicitJavaTypeAccess ); - basicValue.setExplicitJavaTypeAccess( explicitJavaTypeAccess ); - basicValue.setExplicitJdbcTypeAccess( explicitJdbcTypeAccess ); - basicValue.setExplicitMutabilityPlanAccess( explicitMutabilityAccess ); + if ( implicitJavaTypeAccess != null ) { + basicValue.setImplicitJavaTypeAccess( implicitJavaTypeAccess ); + } + + if ( explicitJavaTypeAccess != null ) { + basicValue.setExplicitJavaTypeAccess( explicitJavaTypeAccess ); + } + + if ( explicitJdbcTypeAccess != null ) { + basicValue.setExplicitJdbcTypeAccess( explicitJdbcTypeAccess ); + } + + if ( explicitMutabilityAccess != null ) { + basicValue.setExplicitMutabilityPlanAccess( explicitMutabilityAccess ); + } if ( enumType != null ) { basicValue.setEnumerationStyle( enumType ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/SimpleAttributeBinderTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/SimpleAttributeBinderTests.java new file mode 100644 index 0000000000..9abe908dfc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/SimpleAttributeBinderTests.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.mapping.attributebinder; + +import java.sql.Types; + +import org.hibernate.mapping.BasicValue; +import org.hibernate.mapping.Property; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.DomainModelScope; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@DomainModel( annotatedClasses = { System.class, YesNo.class } ) +@SessionFactory +public class SimpleAttributeBinderTests { + @Test + public void verifyBootModel(DomainModelScope scope) { + scope.withHierarchy( System.class, (descriptor) -> { + final Property activeProp = descriptor.getProperty( "active" ); + final BasicValue activeMapping = (BasicValue) activeProp.getValue(); + + assertThat( activeMapping.getJpaAttributeConverterDescriptor() ).isNotNull(); + + final BasicValue.Resolution resolution = activeMapping.resolve(); + + assertThat( resolution.getDomainJavaDescriptor().getJavaType() ).isEqualTo( Boolean.class ); + assertThat( resolution.getRelationalJavaDescriptor().getJavaType() ).isEqualTo( Character.class ); + assertThat( resolution.getJdbcTypeDescriptor().getJdbcTypeCode() ).isEqualTo( Types.CHAR ); + assertThat( resolution.getValueConverter() ).isNotNull(); + } ); + } + + @Test + public void basicTest(SessionFactoryScope scope) { + scope.inTransaction( (session) -> { + session.createQuery( "from System" ).list(); + } ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/System.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/System.java new file mode 100644 index 0000000000..60dd253fcd --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/System.java @@ -0,0 +1,52 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.mapping.attributebinder; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.Basic; + +@Table(name = "t_systems") +@Entity +public class System { + @Id + public Integer id; + @Basic + public String name; + @YesNo + public boolean active; + + private System() { + // for Hibernate use + } + + public System(Integer id, String name) { + this.id = id; + this.name = name; + } + + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/YesNo.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/YesNo.java new file mode 100644 index 0000000000..58982c35e0 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/YesNo.java @@ -0,0 +1,29 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.mapping.attributebinder; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.hibernate.annotations.AttributeBinderType; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +//tag::attribute-binder-example[] +/** + * Custom annotation applying 'Y'/'N' storage semantics to a boolean. + * + * The important piece here is `@AttributeBinderType` + */ +@Target({METHOD,FIELD}) +@Retention(RUNTIME) +@AttributeBinderType( binder = YesNoBinder.class ) +public @interface YesNo { +} +//end::attribute-binder-example[] diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/YesNoBinder.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/YesNoBinder.java new file mode 100644 index 0000000000..b99e52a9c1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/YesNoBinder.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.mapping.attributebinder; + +import java.sql.Types; + +import org.hibernate.boot.model.convert.internal.InstanceBasedConverterDescriptor; +import org.hibernate.boot.spi.MetadataBuildingContext; +import org.hibernate.mapping.BasicValue; +import org.hibernate.mapping.Column; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.Property; +import org.hibernate.tuple.AttributeBinder; +import org.hibernate.type.YesNoConverter; +import org.hibernate.type.descriptor.java.BasicJavaType; +import org.hibernate.type.descriptor.jdbc.JdbcType; + +//tag::attribute-binder-example[] +/** + * The actual binder responsible for configuring the model objects + */ +public class YesNoBinder implements AttributeBinder { + @Override + public void bind( + YesNo annotation, + MetadataBuildingContext buildingContext, + PersistentClass persistentClass, + Property property) { + final BasicValue booleanValueMapping = (BasicValue) property.getValue(); + + final BasicJavaType javaType = (BasicJavaType) buildingContext.getBootstrapContext() + .getTypeConfiguration() + .getJavaTypeDescriptorRegistry() + .getDescriptor( Boolean.class ); + + final JdbcType jdbcType = buildingContext.getBootstrapContext() + .getTypeConfiguration() + .getJdbcTypeDescriptorRegistry() + .getDescriptor( Types.CHAR ); + + final InstanceBasedConverterDescriptor converter = new InstanceBasedConverterDescriptor( + YesNoConverter.INSTANCE, + buildingContext.getBootstrapContext().getClassmateContext() + ); + + booleanValueMapping.setExplicitJavaTypeAccess( (typeConfiguration) -> javaType ); + booleanValueMapping.setExplicitJdbcTypeAccess( (typeConfiguration) -> jdbcType ); + booleanValueMapping.setJpaAttributeConverterDescriptor( converter ); + } +} +//end::attribute-binder-example[] + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/package-info.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/package-info.java new file mode 100644 index 0000000000..eac1a739bc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/attributebinder/package-info.java @@ -0,0 +1,12 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ + +/** + * Tests (and doc example) for {@link org.hibernate.annotations.AttributeBinderType} + */ +package org.hibernate.orm.test.mapping.attributebinder; + diff --git a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTsTest.java b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTsTest.java index d32c6c96e1..8d23084ae1 100644 --- a/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTsTest.java +++ b/hibernate-envers/src/test/java/org/hibernate/orm/test/envers/integration/strategy/ValidityAuditStrategyRevEndTsTest.java @@ -479,7 +479,9 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe } else { final Dialect dialect = getDialect(); - if ( dialect instanceof MySQLDialect && dialect.getVersion() < 570 && !( dialect instanceof MariaDBDialect ) ) { + if ( dialect instanceof MySQLDialect + && dialect.getVersion().isBefore( 5, 7 ) + && !( dialect instanceof MariaDBDialect ) ) { // MySQL5 DATETIME column type does not contain milliseconds. // MySQL 5.7 supports milliseconds and when MySQL57InnoDBDialect is used, it is assumed that // the column is defined as DATETIME(6). diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG10Dialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG10Dialect.java index 7490d95b34..2b1d55be22 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG10Dialect.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG10Dialect.java @@ -10,6 +10,7 @@ package org.hibernate.spatial.dialect.postgis; import java.util.Map; import org.hibernate.boot.model.TypeContributions; +import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.service.ServiceRegistry; @@ -22,7 +23,7 @@ public class PostgisPG10Dialect extends PostgreSQLDialect { } public PostgisPG10Dialect() { - super( 1000 ); + super( DatabaseVersion.make( 10 ) ); } } diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG93Dialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG93Dialect.java index 9847b33e4d..c2c79d9411 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG93Dialect.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG93Dialect.java @@ -6,6 +6,7 @@ */ package org.hibernate.spatial.dialect.postgis; +import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; @@ -23,10 +24,6 @@ public class PostgisPG93Dialect extends PostgreSQLDialect { } public PostgisPG93Dialect() { - super( 930 ); - } - - public PostgisPG93Dialect(int version) { - super( version ); + super( DatabaseVersion.make( 9, 3 ) ); } } diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG94Dialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG94Dialect.java index 1a0d5a54c3..9fe8717662 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG94Dialect.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG94Dialect.java @@ -6,6 +6,7 @@ */ package org.hibernate.spatial.dialect.postgis; +import org.hibernate.dialect.DatabaseVersion; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; @@ -23,10 +24,6 @@ public class PostgisPG94Dialect extends PostgreSQLDialect { } public PostgisPG94Dialect() { - super( 940 ); - } - - public PostgisPG94Dialect(int version) { - super( version ); + super( DatabaseVersion.make( 9, 4 ) ); } } diff --git a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG95Dialect.java b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG95Dialect.java index ef69999bb8..a403d60e1e 100644 --- a/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG95Dialect.java +++ b/hibernate-spatial/src/main/java/org/hibernate/spatial/dialect/postgis/PostgisPG95Dialect.java @@ -24,8 +24,4 @@ public class PostgisPG95Dialect extends PostgreSQLDialect { public PostgisPG95Dialect() { super(); } - - public PostgisPG95Dialect(int version) { - super( version ); - } } diff --git a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/TestSupportFactories.java b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/TestSupportFactories.java index 593baff8a3..b5ad43ef83 100644 --- a/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/TestSupportFactories.java +++ b/hibernate-spatial/src/test/java/org/hibernate/spatial/testing/TestSupportFactories.java @@ -59,7 +59,7 @@ public class TestSupportFactories { if ( MySQLDialect.class.isAssignableFrom( dialect.getClass() ) ) { - return dialect.getVersion() >= 800 ? MySQL8TestSupport.class : MySQL56TestSupport.class; + return dialect.getVersion().isSameOrAfter( 8 ) ? MySQL8TestSupport.class : MySQL56TestSupport.class; } if ( H2Dialect.class.isAssignableFrom( dialect.getClass() ) ) {