#3295 When isAutoPersistUpdates is used do NOT clear the PersistenceContext

Also make improvements to the test asserts in TestPersistenceContextQueryScope
This commit is contained in:
Rob Bygrave
2024-01-10 23:23:47 +13:00
parent 66234249c6
commit 3576aafffc
6 changed files with 78 additions and 9 deletions
@@ -338,7 +338,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
private int notifyCache(int rows, boolean update) {
if (rows > 0) {
beanDescriptor.contextClear(transaction.persistenceContext());
beanDescriptor.cacheUpdateQuery(update, transaction);
}
return rows;
@@ -783,4 +782,10 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
public int forwardOnlyFetchSize() {
return queryEngine.forwardOnlyFetchSize();
}
public void clearContext() {
if (!transaction.isAutoPersistUpdates()) {
beanDescriptor.contextClear(transaction.persistenceContext());
}
}
}
@@ -78,7 +78,7 @@ public final class PersistRequestOrmUpdate extends PersistRequest {
@Override
public void postExecute() {
OrmUpdateType ormUpdateType = ormUpdate.ormUpdateType();
if (OrmUpdateType.INSERT != ormUpdateType) {
if (OrmUpdateType.INSERT != ormUpdateType && !transaction.isAutoPersistUpdates()) {
beanDescriptor.contextClear(transaction.persistenceContext());
}
if (startNanos > 0) {
@@ -159,7 +159,7 @@ public final class PersistRequestUpdateSql extends PersistRequest {
*/
@Override
public void postExecute() {
if (sqlType != SqlType.SQL_INSERT) {
if (sqlType != SqlType.SQL_INSERT && !transaction.isAutoPersistUpdates()) {
List<BeanDescriptor<?>> descriptors = server.descriptors(tableName);
if (descriptors != null) {
for (BeanDescriptor<?> descriptor : descriptors) {
@@ -74,6 +74,9 @@ public final class CQueryEngine {
if (request.logSql()) {
request.logSql("{0}; --bind({1}) --micros({2}) --rows({3})", query.generatedSql(), query.bindLog(), query.micros(), rows);
}
if (rows > 0) {
request.clearContext();
}
return rows;
} catch (SQLException e) {
throw translate(request, query.bindLog(), query.generatedSql(), e);
@@ -61,6 +61,7 @@ final class CQueryUpdate implements SpiProfileTransactionEvent, CancelableQuery
/**
* Execute the update or delete statement returning the row count.
*/
@SuppressWarnings("resource")
public int execute() throws SQLException {
long startNano = System.nanoTime();
try {
@@ -109,6 +110,7 @@ final class CQueryUpdate implements SpiProfileTransactionEvent, CancelableQuery
pstmt = null;
}
@SuppressWarnings("resource")
@Override
public void profile() {
transaction()
@@ -19,8 +19,6 @@ class TestPersistenceContextQueryScope extends BaseTestCase {
EBasicVer bean = new EBasicVer("first");
DB.save(bean);
//DB.cacheManager().setCaching(EBasicVer.class, true);
try (Transaction txn = DB.beginTransaction()) {
EBasicVer bean1 = DB.find(EBasicVer.class, bean.getId());
@@ -47,7 +45,7 @@ class TestPersistenceContextQueryScope extends BaseTestCase {
.setPersistenceContextScope(QUERY)
.findOne();
// TRANsACTION scope ... same as bean2 and does not hit the DB
// TRANSACTION scope ... same as bean2 and does not hit the DB
EBasicVer bean5 = DB.find(EBasicVer.class)
.setId(bean.getId())
.setUseCache(false) // ignore L2 cache
@@ -57,11 +55,13 @@ class TestPersistenceContextQueryScope extends BaseTestCase {
assertEquals("first", bean.getName());
assertEquals("first", bean1.getName());
assertEquals("second", bean2.getName());
assertEquals("second", bean3.getName());
assertEquals("second", bean5.getName());
assertNotSame(bean1, bean2);
assertNotSame(bean1, bean5);
assertSame(bean2, bean5);
assertNotSame(bean3, bean5);
assertEquals("second", bean3.getName());
DB.delete(bean3);
txn.commit();
@@ -99,7 +99,7 @@ class TestPersistenceContextQueryScope extends BaseTestCase {
.setPersistenceContextScope(QUERY)
.findOne();
// TRANsACTION scope ... same as bean2 and does not hit the DB
// TRANSACTION scope ... same as bean2 and does not hit the DB
EBasicVer bean5 = DB.find(EBasicVer.class)
.setId(bean.getId())
.setUseCache(false) // ignore L2 cache
@@ -113,6 +113,8 @@ class TestPersistenceContextQueryScope extends BaseTestCase {
assertEquals("second", bean5.getName());
assertNotSame(bean1, bean2);
assertNotSame(bean1, bean5);
assertSame(bean2, bean5);
assertNotSame(bean3, bean5);
DB.delete(bean3);
txn.commit();
@@ -151,7 +153,7 @@ class TestPersistenceContextQueryScope extends BaseTestCase {
.setPersistenceContextScope(QUERY)
.findOne();
// TRANsACTION scope ... same as bean2 and does not hit the DB
// TRANSACTION scope ... same as bean2 and does not hit the DB
EBasicVer bean5 = DB.find(EBasicVer.class)
.setId(bean.getId())
.setUseCache(false) // ignore L2 cache
@@ -165,6 +167,63 @@ class TestPersistenceContextQueryScope extends BaseTestCase {
assertEquals("second", bean5.getName());
assertNotSame(bean1, bean2);
assertNotSame(bean1, bean5);
assertSame(bean2, bean5);
assertNotSame(bean3, bean5);
DB.delete(bean3);
txn.commit();
}
}
@Test
void ormUpdateQueryWithAutoPersist_expect_clearsContext() {
EBasicVer bean = new EBasicVer("first");
DB.save(bean);
try (Transaction txn = DB.beginTransaction()) {
txn.setAutoPersistUpdates(true);
EBasicVer bean1 = DB.find(EBasicVer.class, bean.getId());
// do an update of the name in the DB
int rowCount = DB.update(EBasicVer.class)
.set("name", "second")
.where().idEq(bean.getId())
.update();
assertEquals(1, rowCount);
// fetch the bean again... but doesn't hit DB as it
// is in the PersistenceContext which is transaction scoped
EBasicVer bean2 = DB.find(EBasicVer.class)
.setId(bean.getId())
.setUseCache(false) // ignore L2 cache
.findOne();
// QUERY scope hits the DB (doesn't use the existing transactions persistence context)
// ... also explicitly not use bean cache
EBasicVer bean3 = DB.find(EBasicVer.class)
.setId(bean.getId())
.setUseCache(false) // ignore L2 cache
.setPersistenceContextScope(QUERY)
.findOne();
// TRANSACTION scope ... same as bean2 and does not hit the DB
EBasicVer bean5 = DB.find(EBasicVer.class)
.setId(bean.getId())
.setUseCache(false) // ignore L2 cache
.setPersistenceContextScope(TRANSACTION)
.findOne();
assertEquals("first", bean.getName());
assertEquals("first", bean1.getName());
assertEquals("first", bean2.getName()); // This is still first
assertEquals("second", bean3.getName());
assertEquals("first", bean5.getName()); // This is still first
assertSame(bean1, bean2); // Now the same
assertSame(bean1, bean5); // Now the same
assertSame(bean2, bean5);
assertNotSame(bean3, bean5);
DB.delete(bean3);
txn.commit();