From 2b8b33e69424db5ad244aa41f8ab32574ccbe149 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 29 Nov 2022 12:13:27 +0100 Subject: [PATCH] Fix Oracle rowid and sybase value generation issues --- .../userguide/locking/VersionSourceTest.java | 29 +++++++++---------- .../internal/EntityRowIdMappingImpl.java | 5 +++- .../entity/mutation/InsertCoordinator.java | 4 ++- .../mutation/UpdateCoordinatorStandard.java | 24 ++++++++------- .../CurrentTimestampAnnotationTests.java | 1 - .../InDbGenerationsWithAnnotationsTests.java | 1 - .../temporals/GeneratedInstantTests.java | 1 - 7 files changed, 34 insertions(+), 31 deletions(-) diff --git a/documentation/src/test/java/org/hibernate/userguide/locking/VersionSourceTest.java b/documentation/src/test/java/org/hibernate/userguide/locking/VersionSourceTest.java index a40a128348..c7af2d8f0a 100644 --- a/documentation/src/test/java/org/hibernate/userguide/locking/VersionSourceTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/locking/VersionSourceTest.java @@ -10,30 +10,29 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Version; import org.hibernate.annotations.CurrentTimestamp; -import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; -import org.junit.Test; + import java.time.LocalDateTime; -import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; + +import org.junit.jupiter.api.Test; + import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; /** * @author Vlad Mihalcea */ -public class VersionSourceTest extends BaseEntityManagerFunctionalTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { - Person.class - }; - } +@DomainModel( annotatedClasses = VersionSourceTest.Person.class ) +@SessionFactory +public class VersionSourceTest { @Test - public void test() { - doInJPA(this::entityManagerFactory, entityManager -> { + public void test(SessionFactoryScope scope) { + scope.inTransaction( entityManager -> { //tag::locking-optimistic-version-timestamp-source-persist-example[] Person person = new Person(); person.setId(1L); @@ -46,12 +45,12 @@ public class VersionSourceTest extends BaseEntityManagerFunctionalTestCase { //end::locking-optimistic-version-timestamp-source-persist-example[] }); sleep(); - doInJPA(this::entityManagerFactory, entityManager -> { + scope.inTransaction( entityManager -> { Person person = entityManager.find(Person.class, 1L); person.setFirstName("Jane"); }); sleep(); - doInJPA(this::entityManagerFactory, entityManager -> { + scope.inTransaction( entityManager -> { Person person = entityManager.find(Person.class, 1L); person.setFirstName("John"); }); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityRowIdMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityRowIdMappingImpl.java index 430f9967ed..e3069542e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityRowIdMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityRowIdMappingImpl.java @@ -6,6 +6,7 @@ */ package org.hibernate.metamodel.mapping.internal; +import java.sql.Types; import java.util.function.BiConsumer; import org.hibernate.engine.spi.SharedSessionContractImplementor; @@ -27,6 +28,7 @@ import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.basic.BasicResult; import org.hibernate.type.BasicType; import org.hibernate.type.descriptor.java.JavaType; +import org.hibernate.type.spi.TypeConfiguration; /** * @author Nathan Xu @@ -42,7 +44,8 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping { this.tableExpression = tableExpression; this.declaringType = declaringType; this.rowIdType = declaringType.getEntityPersister().getFactory().getTypeConfiguration() - .getBasicTypeForJavaType( Object.class ); + .getBasicTypeRegistry() + .resolve( Object.class, Types.ROWID ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinator.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinator.java index fbee800497..91d4121fa4 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinator.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinator.java @@ -11,6 +11,7 @@ import java.util.List; import org.hibernate.Internal; import org.hibernate.Session; +import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.mutation.JdbcValueBindings; import org.hibernate.engine.jdbc.mutation.MutationExecutor; @@ -402,6 +403,7 @@ public class InsertCoordinator extends AbstractMutationCoordinator { MutationGroupBuilder insertGroupBuilder, boolean[] attributeInclusions) { final List attributeMappings = entityPersister().getAttributeMappings(); + final Dialect dialect = factory().getJdbcServices().getDialect(); insertGroupBuilder.forEachTableMutationBuilder( (builder) -> { final EntityTableMapping tableMapping = (EntityTableMapping) builder.getMutatingTable().getTableMapping(); @@ -425,7 +427,7 @@ public class InsertCoordinator extends AbstractMutationCoordinator { final TableInsertBuilder tableInsertBuilder = insertGroupBuilder.findTableDetailsBuilder( tableNameForMutation ); tableInsertBuilder.addValueColumn( basicAttributeMapping.getSelectionExpression(), - valueGeneration.getDatabaseGeneratedReferencedColumnValue(), + valueGeneration.getDatabaseGeneratedReferencedColumnValue( dialect ), basicAttributeMapping.getJdbcMapping() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java index 85220b470c..6924c4bb7a 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java @@ -14,6 +14,7 @@ import java.util.Set; import org.hibernate.Internal; import org.hibernate.Session; +import org.hibernate.dialect.Dialect; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.batch.spi.BatchKey; @@ -880,6 +881,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple final List attributeMappings = entityPersister().getAttributeMappings(); final boolean[] versionability = entityPersister().getPropertyVersionability(); final OptimisticLockStyle optimisticLockStyle = entityPersister().optimisticLockStyle(); + final Dialect dialect = factory().getJdbcServices().getDialect(); updateGroupBuilder.forEachTableMutationBuilder( (builder) -> { final EntityTableMapping tableMapping = (EntityTableMapping) builder.getMutatingTable().getTableMapping(); @@ -902,16 +904,16 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple && valueGeneration.referenceColumnInSql() ) { // value-generation is only valid for basic attributes final BasicAttributeMapping basicAttributeMapping = (BasicAttributeMapping) attributeMapping; - final String columnValue = valueGeneration.getDatabaseGeneratedReferencedColumnValue() == null - ? "?" - : valueGeneration.getDatabaseGeneratedReferencedColumnValue(); - if ( columnValue != null ) { - tableUpdateBuilder.addValueColumn( - basicAttributeMapping.getSelectionExpression(), - columnValue, - basicAttributeMapping.getJdbcMapping() - ); - } + final String databaseGeneratedValue = valueGeneration.getDatabaseGeneratedReferencedColumnValue( + dialect + ); + tableUpdateBuilder.addValueColumn( + basicAttributeMapping.getSelectionExpression(), + databaseGeneratedValue == null + ? "?" + : databaseGeneratedValue, + basicAttributeMapping.getJdbcMapping() + ); } else if ( versionMapping != null && versionMapping.getVersionAttribute() == attributeMapping ) { @@ -1377,7 +1379,7 @@ public class UpdateCoordinatorStandard extends AbstractMutationCoordinator imple // next, iterate each attribute and build the SET and WHERE clauses applyTableUpdateDetails( // row-id - null, + "", // pass anything here to generate the row id restriction if possible // the "collector" updateGroupBuilder, // oldValues diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/CurrentTimestampAnnotationTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/CurrentTimestampAnnotationTests.java index a9cc5f7d97..faabd1332d 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/CurrentTimestampAnnotationTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/CurrentTimestampAnnotationTests.java @@ -29,7 +29,6 @@ import static org.assertj.core.api.Assertions.assertThat; */ @DomainModel( annotatedClasses = CurrentTimestampAnnotationTests.AuditedEntity.class ) @SessionFactory -@RequiresDialectFeature(feature = DialectFeatureChecks.UsesStandardCurrentTimestampFunction.class, comment = "We rely on current_timestamp being the SQL function name") @RequiresDialectFeature(feature = DialectFeatureChecks.CurrentTimestampHasMicrosecondPrecision.class, comment = "Without this, we might not see an update to the timestamp") public class CurrentTimestampAnnotationTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/InDbGenerationsWithAnnotationsTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/InDbGenerationsWithAnnotationsTests.java index 335a896bd6..233ee24648 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/InDbGenerationsWithAnnotationsTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/InDbGenerationsWithAnnotationsTests.java @@ -36,7 +36,6 @@ import static org.assertj.core.api.Assertions.assertThat; */ @DomainModel( annotatedClasses = InDbGenerationsWithAnnotationsTests.AuditedEntity.class ) @SessionFactory -@RequiresDialectFeature(feature = DialectFeatureChecks.UsesStandardCurrentTimestampFunction.class, comment = "We rely on current_timestamp being the SQL function name") @RequiresDialectFeature(feature = DialectFeatureChecks.CurrentTimestampHasMicrosecondPrecision.class, comment = "Without this, we might not see an update to the timestamp") public class InDbGenerationsWithAnnotationsTests { @Test diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedInstantTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedInstantTests.java index 4d74e26702..1cd8c221d8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedInstantTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedInstantTests.java @@ -29,7 +29,6 @@ import static org.assertj.core.api.Assertions.assertThat; */ @DomainModel( annotatedClasses = GeneratedInstantTests.GeneratedInstantEntity.class ) @SessionFactory -@RequiresDialectFeature(feature = DialectFeatureChecks.UsesStandardCurrentTimestampFunction.class, comment = "We rely on current_timestamp being the SQL function name") @RequiresDialectFeature(feature = DialectFeatureChecks.CurrentTimestampHasMicrosecondPrecision.class, comment = "Without this, we might not see an update to the timestamp") public class GeneratedInstantTests { @Test