#2362 - ENH: Add lock(bean) method as convenience for DB pessimistic locking

This commit is contained in:
Rob Bygrave
2021-09-09 18:18:16 +12:00
parent b739326fca
commit 9fc2ec044d
5 changed files with 113 additions and 11 deletions
@@ -137,6 +137,10 @@ public class TDSpiServer implements SpiServer {
return null;
}
@Override
public void lock(Object bean) {
}
@Override
public Object nextId(Class<?> beanType) {
return null;
@@ -7,12 +7,13 @@ import io.ebean.test.LoggedSql;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.Customer;
import org.tests.model.basic.EBasic;
import org.tests.model.basic.Order;
import org.tests.model.basic.ResetBasicData;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;
public class TestQueryForUpdate extends BaseTestCase {
@@ -40,6 +41,69 @@ public class TestQueryForUpdate extends BaseTestCase {
}
}
@Test
@ForPlatform({ Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
public void testForUpdate_when_alreadyInPCAsReference() {
ResetBasicData.reset();
Order o0 = DB.find(Order.class).orderBy("id").setMaxRows(1).findOne();
Integer customerId = o0.getCustomer().getId();
try (Transaction transaction = DB.beginTransaction()) {
LoggedSql.start();
Order order = DB.find(Order.class, o0.getId());
assert order != null;
Customer customer = order.getCustomer();
assertTrue(DB.beanState(customer).isReference());
assertEquals(customerId, customer.getId());
Customer customer1 = DB.find(Customer.class).where().idEq(customer.getId()).forUpdate().findOne();
assertThat(customer).isSameAs(customer1);
assertThat(customer.getName()).isNotNull();
List<String> sql = LoggedSql.stop();
assertThat(sql).hasSize(2);
assertThat(sql.get(0)).contains("from o_order");
assertThat(sql.get(1)).contains("from o_customer t0 where t0.id = ? for update");
transaction.commit();
}
}
@Test
@ForPlatform({ Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
public void testForUpdate_when_alreadyInPCAsReference_usingLock() {
ResetBasicData.reset();
Order o0 = DB.find(Order.class).orderBy("id").setMaxRows(1).findOne();
Integer customerId = o0.getCustomer().getId();
try (Transaction transaction = DB.beginTransaction()) {
LoggedSql.start();
Order order = DB.find(Order.class, o0.getId());
assert order != null;
Customer customer = order.getCustomer();
assertEquals(customerId, customer.getId());
assertTrue(DB.beanState(customer).isReference());
DB.lock(customer); // load the customer bean using select for update
// bean is now loaded and database row lock held until commit
assertFalse(DB.beanState(customer).isReference());
assertThat(customer.getName()).isNotNull();
List<String> sql = LoggedSql.stop();
assertThat(sql).hasSize(2);
assertThat(sql.get(0)).contains("from o_order");
assertThat(sql.get(1)).contains("from o_customer t0 where t0.id = ? for update");
transaction.commit();
}
}
@Test
@ForPlatform({ Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
public void testForUpdate_when_alreadyInPC() {