Miscellaneous

- Finished DialectVersion
- User Guide tidying
- User Guide section on AttributeBinder
This commit is contained in:
Steve Ebersole 2021-12-09 00:51:40 -06:00
parent fa4b76702c
commit 7a6cef5838
30 changed files with 358 additions and 76 deletions

View File

@ -94,7 +94,7 @@ See the <<chapters/domain/basic_types.adoc#basic-enums-attribute-converter, `Att
==== `@Converter` ==== `@Converter`
The {jpaJavadocUrlPrefix}Converter.html[`@Converter`] annotation is used to specify that the currently annotated {jpaJavadocUrlPrefix}AttributeConverter.html[`AttributeConverter`] implementation can be used as a Jakarta Persistence basic attribute converter. The {jpaJavadocUrlPrefix}Converter.html[`@Converter`] annotation is used to specify that the currently annotated {jpaJavadocUrlPrefix}AttributeConverter.html[`AttributeConverter`] implementation can be used as a Jakarta Persistence basic attribute converter.
specj
If the {jpaJavadocUrlPrefix}Converter.html#autoApply--[`autoApply`] attribute is set to `true`, then the Jakarta Persistence provider will automatically convert all basic attributes with the same Java type as defined by the current converter. If the {jpaJavadocUrlPrefix}Converter.html#autoApply--[`autoApply`] attribute is set to `true`, then the Jakarta Persistence provider will automatically convert all basic attributes with the same Java type as defined by the current converter.
See the <<chapters/domain/basic_types.adoc#basic-enums-attribute-converter, `AttributeConverter`>> section for more info. See the <<chapters/domain/basic_types.adoc#basic-enums-attribute-converter, `AttributeConverter`>> section for more info.
@ -624,22 +624,68 @@ See the <<chapters/locking/Locking.adoc#locking-optimistic, Optimistic locking m
[[annotations-hibernate-any]] [[annotations-hibernate-any]]
==== `@Any` ==== `@Any`
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Any.html[`@Any`] annotation is used to define the *any-to-one* association The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Any.html[`@Any`] annotation is
which can point to one of several entity types. used to define the *any-to-one* association which can point to one of several entity types.
See the <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> section for more info. See the <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> section for more info.
[[annotations-hibernate-anymetadef]] [[annotations-hibernate-anydiscriminator]]
==== `@AnyMetaDef` ==== `@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 <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> section for more info. See the <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> section for more info.
[[annotations-hibernate-anymetadefs]] [[annotations-hibernate-anydiscriminatorvalue]]
==== `@AnyMetaDefs` ==== `@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 <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> 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-hibernate-anydiscriminatorvalue>> annotations.
See the <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> 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 <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> 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 <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> 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 <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> 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 <<chapters/domain/associations.adoc#associations-any,`@Any` mapping>> 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-hibernate-anymetadef>> annotations.
[[annotations-hibernate-attributeaccessor]] [[annotations-hibernate-attributeaccessor]]
==== `@AttributeAccessor` ==== `@AttributeAccessor`
@ -651,6 +697,16 @@ For property/field access type, the Jakarta Persistence <<annotations-jpa-access
However, if this annotation is used with either value="property" or value="field", it will act just as the corresponding usage of the Jakarta Persistence <<annotations-jpa-access>> annotation. However, if this annotation is used with either value="property" or value="field", it will act just as the corresponding usage of the Jakarta Persistence <<annotations-jpa-access>> 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 <<domain-customizing>>.
[[annotations-hibernate-batchsize]] [[annotations-hibernate-batchsize]]
==== `@BatchSize` ==== `@BatchSize`
@ -1341,11 +1397,6 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
See the <<chapters/pc/PersistenceContext.adoc#pc-where-join-table, `@WhereJoinTable` mapping>> section for more info. See the <<chapters/pc/PersistenceContext.adoc#pc-where-join-table, `@WhereJoinTable` mapping>> 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]] [[annotations-hibernate-tenantid]]
==== `@TenantId` ==== `@TenantId`

View File

@ -35,3 +35,4 @@ include::natural_id.adoc[]
include::dynamic_model.adoc[] include::dynamic_model.adoc[]
include::inheritance.adoc[] include::inheritance.adoc[]
include::immutability.adoc[] include::immutability.adoc[]
include::customizing.adoc[]

View File

@ -1,5 +1,5 @@
[[access]] [[access]]
==== Access strategies === Access strategies
:sourcedir: ../../../../../test/java/org/hibernate/userguide/mapping/access :sourcedir: ../../../../../test/java/org/hibernate/userguide/mapping/access
:extrasdir: extras :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. Embeddable types inherit the access strategy from their parent entities.
[[field-based-access]] [[field-based-access]]
===== Field-based access ==== Field-based access
[[access-field-mapping-example]] [[access-field-mapping-example]]
.Field-based access .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 ==== Property-based access
[[access-property-mapping-example]] [[access-property-mapping-example]]
.Property-based access .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. 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. 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. 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. 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]] [[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. 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. This applies to both simple embeddable types as well as for collection of embeddables.

View File

@ -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]
----
====

View File

@ -25,7 +25,7 @@ import static org.junit.Assert.assertEquals;
* @author Vlad Mihalcea * @author Vlad Mihalcea
*/ */
// On H2 1.4.199+ CURRENT_TIMESTAMP returns a timestamp with timezone // 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) @DomainModel(annotatedClasses = Event.class)
@SessionFactory @SessionFactory
public class EmbeddedIdDatabaseGeneratedValueTest { public class EmbeddedIdDatabaseGeneratedValueTest {

View File

@ -489,7 +489,7 @@ public class FirebirdDialect extends Dialect {
@Override @Override
public int getMaxIdentifierLength() { public int getMaxIdentifierLength() {
return getVersion() < 400 ? 31 : 63; return getVersion().isBefore( 4 ) ? 31 : 63;
} }
public IdentifierHelper buildIdentifierHelper( public IdentifierHelper buildIdentifierHelper(
@ -889,7 +889,7 @@ public class FirebirdDialect extends Dialect {
@Override @Override
public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(EntityMappingType entityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) { public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy(EntityMappingType entityDescriptor, RuntimeModelCreationContext runtimeModelCreationContext) {
return getVersion() < 210 return getVersion().isBefore( 2, 1 )
? super.getFallbackSqmInsertStrategy( entityDescriptor, runtimeModelCreationContext ) ? super.getFallbackSqmInsertStrategy( entityDescriptor, runtimeModelCreationContext )
: new GlobalTemporaryTableInsertStrategy( : new GlobalTemporaryTableInsertStrategy(
TemporaryTable.createEntityTable( TemporaryTable.createEntityTable(

View File

@ -53,7 +53,7 @@ public class FirebirdSqlAstTranslator<T extends JdbcOperation> extends AbstractS
@Override @Override
public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) { public void visitBooleanExpressionPredicate(BooleanExpressionPredicate booleanExpressionPredicate) {
if ( getDialect().getVersion() >= 300 ) { if ( getDialect().getVersion().isSameOrAfter( 3 ) ) {
booleanExpressionPredicate.getExpression().accept( this ); booleanExpressionPredicate.getExpression().accept( this );
} }
else { else {
@ -71,7 +71,7 @@ public class FirebirdSqlAstTranslator<T extends JdbcOperation> extends AbstractS
// Before 3.0 there was also no support for window functions // Before 3.0 there was also no support for window functions
// Check if current query part is already row numbering to avoid infinite recursion // Check if current query part is already row numbering to avoid infinite recursion
return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart
&& getDialect().getVersion() >= 300 && !isRowsOnlyFetchClauseType( queryPart ); && getDialect().getVersion().isSameOrAfter( 3 ) && !isRowsOnlyFetchClauseType( queryPart );
} }
@Override @Override
@ -201,7 +201,7 @@ public class FirebirdSqlAstTranslator<T extends JdbcOperation> extends AbstractS
} }
private boolean supportsOffsetFetchClause() { private boolean supportsOffsetFetchClause() {
return getDialect().getVersion() >= 300; return getDialect().getVersion().isSameOrAfter( 3 );
} }
@Override @Override

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.community.dialect; package org.hibernate.community.dialect;
import org.hibernate.dialect.DatabaseVersion;
/** /**
* Dialect for Informix 10 * Dialect for Informix 10
* *
@ -15,7 +17,7 @@ package org.hibernate.community.dialect;
public class Informix10Dialect extends InformixDialect { public class Informix10Dialect extends InformixDialect {
public Informix10Dialect() { public Informix10Dialect() {
super(10); super( DatabaseVersion.make( 10 ) );
} }
} }

View File

@ -154,10 +154,10 @@ public class InformixSqlAstTranslator<T extends JdbcOperation> extends AbstractS
} }
private boolean supportsParameterOffsetFetchExpression() { private boolean supportsParameterOffsetFetchExpression() {
return getDialect().getVersion() >= 11; return getDialect().getVersion().isSameOrAfter( 11 );
} }
private boolean supportsSkipFirstClause() { private boolean supportsSkipFirstClause() {
return getDialect().getVersion() >= 11; return getDialect().getVersion().isSameOrAfter( 11 );
} }
} }

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.community.dialect; package org.hibernate.community.dialect;
import org.hibernate.dialect.DatabaseVersion;
/** /**
* A SQL dialect for Ingres 10 and later versions. * A SQL dialect for Ingres 10 and later versions.
* <p/> * <p/>
@ -23,7 +25,7 @@ package org.hibernate.community.dialect;
public class Ingres10Dialect extends IngresDialect { public class Ingres10Dialect extends IngresDialect {
public Ingres10Dialect() { public Ingres10Dialect() {
super(1000); super( DatabaseVersion.make( 10 ) );
} }
} }

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.community.dialect; package org.hibernate.community.dialect;
import org.hibernate.dialect.DatabaseVersion;
/** /**
* A SQL dialect for Ingres 9.3 and later versions. * A SQL dialect for Ingres 9.3 and later versions.
* <p/> * <p/>
@ -29,7 +31,7 @@ package org.hibernate.community.dialect;
public class Ingres9Dialect extends IngresDialect { public class Ingres9Dialect extends IngresDialect {
public Ingres9Dialect() { public Ingres9Dialect() {
super(930); super( DatabaseVersion.make( 9, 3 ) );
} }
} }

View File

@ -165,11 +165,11 @@ public class IngresSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
} }
private boolean supportsParameterOffsetFetchExpression() { private boolean supportsParameterOffsetFetchExpression() {
return getDialect().getVersion() >= 930; return getDialect().getVersion().isSameOrAfter( 9, 3 );
} }
private boolean supportsOffsetFetchClause() { private boolean supportsOffsetFetchClause() {
return getDialect().getVersion() >= 930; return getDialect().getVersion().isSameOrAfter( 9, 3 );
} }
} }

View File

@ -64,7 +64,7 @@ public class MaxDBSqlAstTranslator<T extends JdbcOperation> extends AbstractSqlA
@Override @Override
protected void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression, boolean inSelect) { protected void visitCaseSearchedExpression(CaseSearchedExpression caseSearchedExpression, boolean inSelect) {
// Couldn't find documentation for older versions, but 7.7 supports ANSI style case expressions // 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 ); visitDecodeCaseSearchedExpression( caseSearchedExpression );
} }
else { else {

View File

@ -48,7 +48,7 @@ public class SQLiteSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
@Override @Override
protected void renderMaterializationHint(CteMaterialization materialization) { protected void renderMaterializationHint(CteMaterialization materialization) {
if ( getDialect().getVersion() >= 335 ) { if ( getDialect().getVersion().isSameOrAfter( 3, 3, 5 ) ) {
if ( materialization == CteMaterialization.NOT_MATERIALIZED ) { if ( materialization == CteMaterialization.NOT_MATERIALIZED ) {
appendSql( "not " ); appendSql( "not " );
} }
@ -58,7 +58,7 @@ public class SQLiteSqlAstTranslator<T extends JdbcOperation> extends AbstractSql
@Override @Override
public boolean supportsFilterClause() { public boolean supportsFilterClause() {
return getDialect().getVersion() >= 330; return getDialect().getVersion().isSameOrAfter( 3, 3 );
} }
@Override @Override

View File

@ -7,12 +7,16 @@
package org.hibernate.community.dialect; package org.hibernate.community.dialect;
import java.sql.Types;
import java.util.Map;
import org.hibernate.LockOptions; 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.RowLockStrategy;
import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TimeZoneSupport; import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.dialect.identity.IdentityColumnSupport; import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.community.dialect.identity.SybaseAnywhereIdentityColumnSupport;
import org.hibernate.dialect.pagination.LimitHandler; import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler; import org.hibernate.dialect.pagination.TopLimitHandler;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; 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.ast.tree.Statement;
import org.hibernate.sql.exec.spi.JdbcOperation; import org.hibernate.sql.exec.spi.JdbcOperation;
import java.sql.Types;
import java.util.Map;
/** /**
* SQL Dialect for Sybase Anywhere * SQL Dialect for Sybase Anywhere
* (Tested on ASA 8.x) * (Tested on ASA 8.x)
@ -34,18 +35,18 @@ import java.util.Map;
public class SybaseAnywhereDialect extends SybaseDialect { public class SybaseAnywhereDialect extends SybaseDialect {
public SybaseAnywhereDialect() { public SybaseAnywhereDialect() {
this( 800, false ); this( DatabaseVersion.make( 8 ), false );
} }
public SybaseAnywhereDialect(DialectResolutionInfo info){ public SybaseAnywhereDialect(DialectResolutionInfo info){
this( this(
info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10, info,
info.getDriverName() != null && info.getDriverName().contains( "jTDS" ) info.getDriverName() != null && info.getDriverName().contains( "jTDS" )
); );
registerKeywords( info ); registerKeywords( info );
} }
public SybaseAnywhereDialect(int version, boolean jtdsDriver) { public SybaseAnywhereDialect(DatabaseVersion version, boolean jtdsDriver) {
super( version, jtdsDriver ); super( version, jtdsDriver );
registerColumnType( Types.BIGINT, "bigint" ); registerColumnType( Types.BIGINT, "bigint" );
@ -132,30 +133,30 @@ public class SybaseAnywhereDialect extends SybaseDialect {
@Override @Override
public RowLockStrategy getWriteRowLockStrategy() { public RowLockStrategy getWriteRowLockStrategy() {
return getVersion() >= 1000 ? RowLockStrategy.COLUMN : RowLockStrategy.TABLE; return getVersion().isSameOrAfter( 10 ) ? RowLockStrategy.COLUMN : RowLockStrategy.TABLE;
} }
@Override @Override
public String getForUpdateString() { public String getForUpdateString() {
return getVersion() < 1000 ? "" : " for update"; return getVersion().isBefore( 10 ) ? "" : " for update";
} }
@Override @Override
public String getForUpdateString(String aliases) { public String getForUpdateString(String aliases) {
return getVersion() < 1000 return getVersion().isBefore( 10 )
? "" ? ""
: getForUpdateString() + " of " + aliases; : getForUpdateString() + " of " + aliases;
} }
@Override @Override
public String appendLockHint(LockOptions mode, String tableName) { 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 @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) { public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) {
return getVersion() < 1000 return getVersion().isBefore( 10 )
? super.applyLocksToSql( sql, aliasedLockOptions, keyColumnNames ) ? super.applyLocksToSql( sql, aliasedLockOptions, keyColumnNames )
: sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString(); : sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString();
} }

View File

@ -95,7 +95,7 @@ public class SybaseAnywhereSqlAstTranslator<T extends JdbcOperation> extends Abs
@Override @Override
protected boolean renderTableReference(TableReference tableReference, LockMode lockMode) { protected boolean renderTableReference(TableReference tableReference, LockMode lockMode) {
super.renderTableReference( tableReference, lockMode ); super.renderTableReference( tableReference, lockMode );
if ( getDialect().getVersion() < 1000 ) { if ( getDialect().getVersion().isBefore( 10 ) ) {
if ( LockMode.READ.lessThan( lockMode ) ) { if ( LockMode.READ.lessThan( lockMode ) ) {
appendSql( " holdlock" ); appendSql( " holdlock" );
} }
@ -106,7 +106,7 @@ public class SybaseAnywhereSqlAstTranslator<T extends JdbcOperation> extends Abs
@Override @Override
protected void renderForUpdateClause(QuerySpec querySpec, ForUpdateClause forUpdateClause) { protected void renderForUpdateClause(QuerySpec querySpec, ForUpdateClause forUpdateClause) {
if ( getDialect().getVersion() < 1000 ) { if ( getDialect().getVersion().isBefore( 10 ) ) {
return; return;
} }
super.renderForUpdateClause( querySpec, forUpdateClause ); super.renderForUpdateClause( querySpec, forUpdateClause );
@ -114,7 +114,7 @@ public class SybaseAnywhereSqlAstTranslator<T extends JdbcOperation> extends Abs
@Override @Override
protected boolean needsRowsToSkip() { protected boolean needsRowsToSkip() {
return getDialect().getVersion() < 900; return getDialect().getVersion().isBefore( 9 );
} }
@Override @Override
@ -127,7 +127,7 @@ public class SybaseAnywhereSqlAstTranslator<T extends JdbcOperation> extends Abs
@Override @Override
protected void visitSqlSelections(SelectClause selectClause) { protected void visitSqlSelections(SelectClause selectClause) {
if ( getDialect().getVersion() < 900 ) { if ( getDialect().getVersion().isBefore( 9 ) ) {
renderTopClause( (QuerySpec) getQueryPartStack().getCurrent(), true, true ); renderTopClause( (QuerySpec) getQueryPartStack().getCurrent(), true, true );
} }
else { else {
@ -151,7 +151,7 @@ public class SybaseAnywhereSqlAstTranslator<T extends JdbcOperation> extends Abs
@Override @Override
public void visitOffsetFetchClause(QueryPart queryPart) { public void visitOffsetFetchClause(QueryPart queryPart) {
// Sybase Anywhere only supports the TOP clause // 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 ) { && useOffsetFetchClause( queryPart ) && queryPart.getOffsetClauseExpression() != null ) {
throw new IllegalArgumentException( "Can't emulate offset clause in subquery" ); throw new IllegalArgumentException( "Can't emulate offset clause in subquery" );
} }

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.community.dialect; package org.hibernate.community.dialect;
import org.hibernate.dialect.DatabaseVersion;
/** /**
* A dialect for the Teradata 14 * A dialect for the Teradata 14
* *
@ -15,7 +17,7 @@ package org.hibernate.community.dialect;
public class Teradata14Dialect extends TeradataDialect { public class Teradata14Dialect extends TeradataDialect {
public Teradata14Dialect() { public Teradata14Dialect() {
super(14); super( DatabaseVersion.make( 14 ) );
} }
} }

View File

@ -36,7 +36,7 @@ public class TeradataSqlAstTranslator<T extends JdbcOperation> extends AbstractS
@Override @Override
public void visitQuerySpec(QuerySpec querySpec) { public void visitQuerySpec(QuerySpec querySpec) {
if ( querySpec.isRoot() && getDialect().getVersion() >= 14 ) { if ( querySpec.isRoot() && getDialect().getVersion().isSameOrAfter( 14 ) ) {
final ForUpdateClause forUpdateClause = new ForUpdateClause(); final ForUpdateClause forUpdateClause = new ForUpdateClause();
forUpdateClause.merge( getLockOptions() ); forUpdateClause.merge( getLockOptions() );
super.renderForUpdateClause( querySpec, forUpdateClause ); super.renderForUpdateClause( querySpec, forUpdateClause );

View File

@ -1312,12 +1312,25 @@ public class BasicValueBinder<T> implements JdbcTypeDescriptorIndicators {
basicValue.setTypeParameters( (Map) parameters ); basicValue.setTypeParameters( (Map) parameters );
} }
basicValue.setJpaAttributeConverterDescriptor( converterDescriptor ); if ( converterDescriptor != null ) {
basicValue.setJpaAttributeConverterDescriptor( converterDescriptor );
}
basicValue.setImplicitJavaTypeAccess( implicitJavaTypeAccess ); if ( implicitJavaTypeAccess != null ) {
basicValue.setExplicitJavaTypeAccess( explicitJavaTypeAccess ); basicValue.setImplicitJavaTypeAccess( implicitJavaTypeAccess );
basicValue.setExplicitJdbcTypeAccess( explicitJdbcTypeAccess ); }
basicValue.setExplicitMutabilityPlanAccess( explicitMutabilityAccess );
if ( explicitJavaTypeAccess != null ) {
basicValue.setExplicitJavaTypeAccess( explicitJavaTypeAccess );
}
if ( explicitJdbcTypeAccess != null ) {
basicValue.setExplicitJdbcTypeAccess( explicitJdbcTypeAccess );
}
if ( explicitMutabilityAccess != null ) {
basicValue.setExplicitMutabilityPlanAccess( explicitMutabilityAccess );
}
if ( enumType != null ) { if ( enumType != null ) {
basicValue.setEnumerationStyle( enumType ); basicValue.setEnumerationStyle( enumType );

View File

@ -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();
} );
}
}

View File

@ -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;
}
}

View File

@ -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[]

View File

@ -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<YesNo> {
@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[]

View File

@ -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;

View File

@ -479,7 +479,9 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
} }
else { else {
final Dialect dialect = getDialect(); 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. // MySQL5 DATETIME column type does not contain milliseconds.
// MySQL 5.7 supports milliseconds and when MySQL57InnoDBDialect is used, it is assumed that // MySQL 5.7 supports milliseconds and when MySQL57InnoDBDialect is used, it is assumed that
// the column is defined as DATETIME(6). // the column is defined as DATETIME(6).

View File

@ -10,6 +10,7 @@ package org.hibernate.spatial.dialect.postgis;
import java.util.Map; import java.util.Map;
import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
@ -22,7 +23,7 @@ public class PostgisPG10Dialect extends PostgreSQLDialect {
} }
public PostgisPG10Dialect() { public PostgisPG10Dialect() {
super( 1000 ); super( DatabaseVersion.make( 10 ) );
} }
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.spatial.dialect.postgis; package org.hibernate.spatial.dialect.postgis;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
@ -23,10 +24,6 @@ public class PostgisPG93Dialect extends PostgreSQLDialect {
} }
public PostgisPG93Dialect() { public PostgisPG93Dialect() {
super( 930 ); super( DatabaseVersion.make( 9, 3 ) );
}
public PostgisPG93Dialect(int version) {
super( version );
} }
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.spatial.dialect.postgis; package org.hibernate.spatial.dialect.postgis;
import org.hibernate.dialect.DatabaseVersion;
import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
@ -23,10 +24,6 @@ public class PostgisPG94Dialect extends PostgreSQLDialect {
} }
public PostgisPG94Dialect() { public PostgisPG94Dialect() {
super( 940 ); super( DatabaseVersion.make( 9, 4 ) );
}
public PostgisPG94Dialect(int version) {
super( version );
} }
} }

View File

@ -24,8 +24,4 @@ public class PostgisPG95Dialect extends PostgreSQLDialect {
public PostgisPG95Dialect() { public PostgisPG95Dialect() {
super(); super();
} }
public PostgisPG95Dialect(int version) {
super( version );
}
} }

View File

@ -59,7 +59,7 @@ public class TestSupportFactories {
if ( MySQLDialect.class.isAssignableFrom( dialect.getClass() ) ) { 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() ) ) { if ( H2Dialect.class.isAssignableFrom( dialect.getClass() ) ) {