Fix Oracle rowid and sybase value generation issues

This commit is contained in:
Christian Beikov 2022-11-29 12:13:27 +01:00
parent ad019fccec
commit 2b8b33e694
7 changed files with 34 additions and 31 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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