diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e6bb38b..9663666 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -30,7 +30,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [8]
+ java: [8, 17, 21]
steps:
- name: Checkout source
uses: actions/checkout@v4
diff --git a/pom.xml b/pom.xml
index 0d5329c..021279d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -305,6 +305,7 @@
[1.8,)
+ 1.18.30
-Xdoclint:none
diff --git a/src/main/java/com/sleepycat/berkeley/spring/boot/BerkeleyTemplate.java b/src/main/java/com/sleepycat/berkeley/spring/boot/BerkeleyTemplate.java
index fbbb017..f51f257 100644
--- a/src/main/java/com/sleepycat/berkeley/spring/boot/BerkeleyTemplate.java
+++ b/src/main/java/com/sleepycat/berkeley/spring/boot/BerkeleyTemplate.java
@@ -161,12 +161,34 @@ public void otherMethod(){
List list = myDbEnvironment.getDatabaseNames();//取得当前环境下数据库名称列表
System.out.println(list);
- // JE requires the handle to be closed before truncation. Reopen it so
- // this template remains usable after clearing the records.
- com.sleepycat.je.DatabaseConfig config = myDatabase.getConfig();
- myDatabase.close();
- long deleteNum = env.truncateDatabase(null, databaseName, true);
- myDatabase = env.openDatabase(null, databaseName, config);
+ // Delete in a transaction while keeping the shared Database handle open.
+ Transaction txn = env.beginTransaction(null, null);
+ Cursor cursor = null;
+ long deleteNum = 0;
+ boolean committed = false;
+ try {
+ cursor = myDatabase.openCursor(txn, null);
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry value = new DatabaseEntry();
+ while (cursor.getNext(key, value, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
+ cursor.delete();
+ deleteNum++;
+ }
+ cursor.close();
+ cursor = null;
+ txn.commit();
+ committed = true;
+ } finally {
+ try {
+ if (cursor != null) {
+ cursor.close();
+ }
+ } finally {
+ if (!committed) {
+ txn.abort();
+ }
+ }
+ }
System.out.println(deleteNum);
diff --git a/src/test/java/com/sleepycat/berkeley/spring/boot/BerkeleyTest.java b/src/test/java/com/sleepycat/berkeley/spring/boot/BerkeleyTest.java
index 3d393ba..88cf509 100644
--- a/src/test/java/com/sleepycat/berkeley/spring/boot/BerkeleyTest.java
+++ b/src/test/java/com/sleepycat/berkeley/spring/boot/BerkeleyTest.java
@@ -29,6 +29,7 @@
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
class BerkeleyTest {
@TempDir Path home;
@@ -40,6 +41,7 @@ class BerkeleyTest {
void openDatabase() {
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setAllowCreate(true);
+ envConfig.setConfigParam("je.freeDisk", "0");
envConfig.setTransactional(true);
environment = new Environment(home.toFile(), envConfig);
DatabaseConfig dbConfig = new DatabaseConfig();
@@ -80,12 +82,27 @@ void storesPrimitiveValues() {
@Test
- void truncatesAndReopensTheDatabase() {
+ void clearsAllRecordsWithoutReplacingSharedHandle() {
template.writeToDatabase("keep", "before", true);
+ template.writeToDatabase("second", "before", true);
template.otherMethod();
- database = template.getDatabase();
+ assertSame(database, template.getDatabase());
assertEquals("", template.readFromDatabase("keep"));
+ assertEquals("", template.readFromDatabase("second"));
template.writeToDatabase("after", "value", true);
assertEquals("value", template.readFromDatabase("after"));
}
+ @Test
+ void failedClearLeavesTheSharedHandleUntouched() {
+ Database failing = mock(Database.class);
+ when(failing.getDatabaseName()).thenReturn("items");
+ when(failing.getEnvironment()).thenReturn(environment);
+ when(failing.openCursor(any(com.sleepycat.je.Transaction.class), isNull())).thenThrow(new IllegalStateException("cursor unavailable"));
+ template.setDatabase(failing);
+ assertThrows(IllegalStateException.class, () -> template.otherMethod());
+ assertSame(failing, template.getDatabase());
+ template.setDatabase(database);
+ template.writeToDatabase("after-failure", "valid", true);
+ assertEquals("valid", template.readFromDatabase("after-failure"));
+ }
}