From 76b2f92f396f3f42cfba524ef734c5c49fc59ebc Mon Sep 17 00:00:00 2001 From: Gavin Date: Sun, 1 Jan 2023 16:09:26 +0100 Subject: [PATCH] HHH-15958 support the @RowId annotation on DB2 LUW ... and perhaps also on DB2 for z and i (no way to test it) --- .../java/org/hibernate/annotations/RowId.java | 26 +++++++++++++------ .../org/hibernate/dialect/DB2Dialect.java | 20 ++++++++++++-- .../org/hibernate/dialect/DB2iDialect.java | 23 +++++++++++++++- .../org/hibernate/dialect/DB2zDialect.java | 22 +++++++++++++++- .../java/org/hibernate/dialect/Dialect.java | 22 +++++++++++++++- .../java/org/hibernate/dialect/H2Dialect.java | 2 +- .../org/hibernate/dialect/OracleDialect.java | 2 +- .../hibernate/dialect/PostgreSQLDialect.java | 2 +- .../org/hibernate/dialect/TiDBDialect.java | 1 - .../entity/AbstractEntityPersister.java | 7 +---- .../internal/StandardTableExporter.java | 6 +++++ .../hibernate/orm/test/rowid/RowIdTest.java | 2 +- .../org/hibernate/testing/DialectChecks.java | 2 +- 13 files changed, 112 insertions(+), 25 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/annotations/RowId.java b/hibernate-core/src/main/java/org/hibernate/annotations/RowId.java index bbbcfb6389..3fd7a9fbb1 100644 --- a/hibernate-core/src/main/java/org/hibernate/annotations/RowId.java +++ b/hibernate-core/src/main/java/org/hibernate/annotations/RowId.java @@ -13,25 +13,35 @@ import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - * Specifies that an Oracle-style {@code rowid} should be used in SQL - * {@code update} statements for an entity, instead of the primary key. + * Specifies that a {@code rowid}-like column or pseudo-column should be + * used as the row locator in SQL {@code update} statements for an entity, + * instead of the primary key of the table. *

* If the {@linkplain org.hibernate.dialect.Dialect SQL dialect} does - * not support some sort of {@code rowid}, this annotation is ignored. + * not support some sort of {@code rowid}-like column or pseudo-column, + * then this annotation is ignored, and the primary key is used as the + * row locator. * * @author Steve Ebersole + * + * @see org.hibernate.dialect.Dialect#rowId */ @Target(TYPE) @Retention(RUNTIME) public @interface RowId { /** - * Specifies the {@code rowid} identifier. + * Specifies the name of the {@code rowid}-like column for databases + * where the column is declared explicitly in DDL. *

- * For example, on Oracle, this should be just {@code "rowid"}. + * It is not necessary to specify the name for databases where + * the {@code rowid}-like value is an implicitly-existing pseudo-column, + * and on those databases, this annotation member is ignored. * - * @deprecated the {@code rowid} identifier is now inferred - * automatically from the {@link org.hibernate.dialect.Dialect} + * @apiNote Previously, this annotation member was required. But the + * name of the column it is now usually determined by calling + * {@link org.hibernate.dialect.Dialect#rowId}, and so this + * member is now usually ignored. The exception is for certain + * flavors of DB2. */ - @Deprecated(since = "6.2") String value() default ""; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index 939d711bc4..292f972241 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -948,8 +948,8 @@ public class DB2Dialect extends Dialect { @Override public IdentifierHelper buildIdentifierHelper(IdentifierHelperBuilder builder, DatabaseMetaData dbMetaData) throws SQLException { - builder.setAutoQuoteInitialUnderscore(true); - return super.buildIdentifierHelper(builder, dbMetaData); + builder.setAutoQuoteInitialUnderscore( true ); + return super.buildIdentifierHelper( builder, dbMetaData ); } @Override @@ -976,4 +976,20 @@ public class DB2Dialect extends Dialect { public String getCreateUserDefinedTypeExtensionsString() { return " instantiable mode db2sql"; } + + /** + * The more "standard" syntax is {@code rid_bit(alias)} but here we use {@code alias.rowid}. + *

+ * There is also an alternative {@code rid()} of type {@code bigint}, but it cannot be used + * with partitioning. + */ + @Override + public String rowId(String rowId) { + return "rowid"; + } + + @Override + public int rowIdSqlType() { + return VARBINARY; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java index 4edb35dd89..8a8a791b14 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2iDialect.java @@ -28,8 +28,10 @@ import org.hibernate.sql.exec.spi.JdbcOperation; import java.util.List; +import static org.hibernate.type.SqlTypes.ROWID; + /** - * A SQL dialect for DB2 for iSeries version 7.1 and above, previously known as "DB2/400". + * A SQL dialect for DB2 for IBM i version 7.1 and above, previously known as "DB2/400". * * @author Peter DeGregorio (pdegregorio) * @author Christian Beikov @@ -149,4 +151,23 @@ public class DB2iDialect extends DB2Dialect { } }; } + + // I speculate that this is a correct implementation of rowids for DB2 for i, + // just on the basis of the DB2 docs, but I currently have no way to test it + // Note that the implementation inherited from DB2Dialect for LUW will not work! + + @Override + public String rowId(String rowId) { + return rowId.isEmpty() ? "rowid_" : rowId; + } + + @Override + public int rowIdSqlType() { + return ROWID; + } + + @Override + public String getRowIdColumnString(String rowId) { + return rowId( rowId ) + " rowid not null generated always"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java index b275ef4db1..4f6874dbae 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2zDialect.java @@ -30,10 +30,11 @@ import jakarta.persistence.TemporalType; import java.util.List; +import static org.hibernate.type.SqlTypes.ROWID; import static org.hibernate.type.SqlTypes.TIMESTAMP_WITH_TIMEZONE; /** - * A SQL dialect for DB2 for z/OS version 12.1 and above, previously known as : + * A SQL dialect for DB2 for z/OS version 12.1 and above, previously known as: *