Fix Oracle rowid and sybase value generation issues
This commit is contained in:
parent
ad019fccec
commit
2b8b33e694
|
@ -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");
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue