Add Context method to uncache all entities

This commit is contained in:
Chris Wilper
2021-04-28 09:29:36 -04:00
parent c3cbdd15fe
commit 8ea664adb2
5 changed files with 86 additions and 12 deletions

View File

@@ -817,7 +817,19 @@ public class Context implements AutoCloseable {
}
/**
* Remove an entity from the cache. This is necessary when batch processing a large number of items.
* Remove all entities from the cache and reload the current user entity. This is useful when batch processing
* a large number of entities when the calling code requires the cache to be completely cleared before continuing.
*
* @throws SQLException if a database error occurs.
*/
public void uncacheEntities() throws SQLException {
dbConnection.uncacheEntities();
reloadContextBoundEntities();
}
/**
* Remove an entity from the cache. This is useful when batch processing a large number of entities
* when the calling code needs to retain some items in the cache while removing others.
*
* @param entity The entity to reload
* @param <E> The class of the enity. The entity must implement the {@link ReloadableEntity} interface.

View File

@@ -124,28 +124,38 @@ public interface DBConnection<T> {
public long getCacheSize() throws SQLException;
/**
* Reload a DSpace object from the database. This will make sure the object
* Reload an entity from the database. This will make sure the object
* is valid and stored in the cache. The returned object should be used
* henceforth instead of the passed object.
*
* @param <E> type of {@link entity}
* @param entity The DSpace object to reload
* @param <E> type of entity.
* @param entity The entity to reload.
* @return the reloaded entity.
* @throws java.sql.SQLException passed through.
* @throws SQLException passed through.
*/
public <E extends ReloadableEntity> E reloadEntity(E entity) throws SQLException;
/**
* Remove a DSpace object from the session cache when batch processing a
* large number of objects.
* Remove all entities from the session cache.
*
* <p>Objects removed from cache are not saved in any way. Therefore, if you
* have modified an object, you should be sure to {@link commit()} changes
* <p>Entities removed from cache are not saved in any way. Therefore, if you
* have modified any entities, you should be sure to {@link #commit()} changes
* before calling this method.
*
* @param <E> Type of {@link entity}
* @param entity The DSpace object to decache.
* @throws java.sql.SQLException passed through.
* @throws SQLException passed through.
*/
public void uncacheEntities() throws SQLException;
/**
* Remove an entity from the session cache.
*
* <p>Entities removed from cache are not saved in any way. Therefore, if you
* have modified the entity, you should be sure to {@link #commit()} changes
* before calling this method.
*
* @param <E> Type of entity.
* @param entity The entity to decache.
* @throws SQLException passed through.
*/
public <E extends ReloadableEntity> void uncacheEntity(E entity) throws SQLException;
}

View File

@@ -243,6 +243,11 @@ public class HibernateDBConnection implements DBConnection<Session> {
}
}
@Override
public void uncacheEntities() throws SQLException {
getSession().clear();
}
/**
* Evict an entity from the hibernate cache.
* <P>

View File

@@ -558,4 +558,29 @@ public class ContextTest extends AbstractUnitTest {
cleanupContext(instance);
}
@Test
public void testUncacheEntities() throws Throwable {
// To set up the test, ensure the cache contains more than the current user entity
groupService.findByName(context, Group.ANONYMOUS);
assertTrue("Cache size should be greater than one", context.getDBConnection().getCacheSize() > 1);
context.uncacheEntities();
assertThat("Cache size should be one (current user)", context.getDBConnection().getCacheSize(), equalTo(1L));
context.reloadEntity(context.getCurrentUser());
assertThat("Cache should only contain the current user", context.getDBConnection().getCacheSize(), equalTo(1L));
}
@Test
public void testUncacheEntity() throws Throwable {
// Remember the cache size after loading an entity
Group group = groupService.findByName(context, Group.ANONYMOUS);
long oldCacheSize = context.getDBConnection().getCacheSize();
// Uncache the entity
context.uncacheEntity(group);
long newCacheSize = context.getDBConnection().getCacheSize();
assertThat("Cache size should be reduced by one", newCacheSize, equalTo(oldCacheSize - 1));
}
}

View File

@@ -205,6 +205,28 @@ public class HibernateDBConnectionTest extends AbstractUnitTest {
.contains(person));
}
/**
* Test of uncacheEntities method
*/
@Test
public void testUncacheEntities() throws SQLException {
// Get DBConnection associated with DSpace Context
HibernateDBConnection dbConnection = (HibernateDBConnection) context.getDBConnection();
EPerson person = context.getCurrentUser();
assertTrue("Current user should be cached in session", dbConnection.getSession()
.contains(person));
dbConnection.uncacheEntities();
assertFalse("Current user should be gone from cache", dbConnection.getSession()
.contains(person));
// Test ability to reload an uncached entity
person = dbConnection.reloadEntity(person);
assertTrue("Current user should be cached back in session", dbConnection.getSession()
.contains(person));
}
/**
* Test of uncacheEntity method
*/