Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ protected BatchKeyAccess resolveBatchKeyAccess(boolean dynamicUpdate, SharedSess
if ( !dynamicUpdate
&& !entityPersister().optimisticLockStyle().isAllOrDirty()
&& session.getTransactionCoordinator() != null
&& session.getTransactionCoordinator().isTransactionActive() ) {
&& session.getTransactionCoordinator().isTransactionActive()
&& (
session.getSessionFactory().getSessionFactoryOptions().isJdbcBatchVersionedData()
|| !entityPersister().isVersioned() ) ) {
return this::getBatchKey;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.hibernate.orm.test.batch;

import java.io.Serializable;
import java.util.List;

import org.hibernate.cfg.BatchSettings;

import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.RollbackException;
import jakarta.persistence.Version;

@Jpa(
annotatedClasses = BatchOffOnlyForOptimisticallyLocked.Something.class,
properties = {
@Setting(name = BatchSettings.STATEMENT_BATCH_SIZE, value = "10"),
@Setting(name = BatchSettings.BATCH_VERSIONED_DATA, value = "false")
}
)
@JiraKey( "HHH-18621" )
@SkipForDialect(dialectClass = MariaDBDialect.class, majorVersion = 11, minorVersion = 6, microVersion = 2, reason = "MariaDB will throw an error DB_RECORD_CHANGED when acquiring a lock on a record that have changed")
public class BatchOffOnlyForOptimisticallyLocked {
@Test
public void testMultiUpdateOfConcurrentlyModified(EntityManagerFactoryScope scope) {
scope.inTransaction( em -> {
em.persist( new Something( "First" ) );
em.persist( new Something( "Second" ) );
} );

final RollbackException ex = Assertions.assertThrows( RollbackException.class, () -> {
scope.inTransaction( em -> {
final List<Something> subjects = em.createQuery( "select s from Something s", Something.class )
.getResultList();
scope.inTransaction(
competitorEm -> competitorEm.find( Something.class, subjects.get( 0 ).id ).name = "Outrun"
);
for ( Something something : subjects ) {
something.name += " modified";
}
} );
} );
Assertions.assertInstanceOf( OptimisticLockException.class, ex.getCause(), "The cause of rollback" );
Assertions.assertNotNull( ( (OptimisticLockException) ex.getCause() ).getEntity(), "OLE references an entity" );
}

//Has to be Serializable, otherwise it is not deemed safe to include in the OLE.
@Entity(name = "Something")
public static class Something implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
public String name;
@Version
public long version;

public Something() {
}

public Something(String name) {
this.name = name;
}
}
}