This is an automated email from the ASF dual-hosted git repository.
mchades pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 1ff0802039 [#7744] improvement(core): allow nested SqlSession call
(#8242)
1ff0802039 is described below
commit 1ff08020398925893c66327b78320b2cb9b90c5f
Author: mchades <[email protected]>
AuthorDate: Tue Aug 26 21:58:42 2025 +0800
[#7744] improvement(core): allow nested SqlSession call (#8242)
### What changes were proposed in this pull request?
- add sessionCount for lifecycle management
### Why are the changes needed?
Fix: #7744
### Does this PR introduce _any_ user-facing change?
no
### How was this patch tested?
tests added
---
.../relational/service/GroupMetaService.java | 4 +-
.../relational/service/JobTemplateMetaService.java | 2 +-
.../relational/service/ModelMetaService.java | 2 +-
.../service/ModelVersionMetaService.java | 10 +-
.../relational/service/PolicyMetaService.java | 8 +-
.../relational/service/RoleMetaService.java | 8 +-
.../relational/service/TableColumnMetaService.java | 2 +-
.../relational/service/TableMetaService.java | 4 +-
.../storage/relational/service/TagMetaService.java | 12 +-
.../relational/service/UserMetaService.java | 4 +-
.../storage/relational/session/SqlSessions.java | 83 ++++++++-----
.../storage/relational/utils/SessionUtils.java | 135 ++++++++-------------
.../storage/relational/session/TestSqlSession.java | 6 +
13 files changed, 136 insertions(+), 144 deletions(-)
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
index 4329b3a0a1..e5a32171df 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
@@ -288,12 +288,12 @@ public class GroupMetaService {
SessionUtils.doMultipleWithCommit(
() ->
groupDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
GroupMetaMapper.class,
mapper ->
mapper.deleteGroupMetasByLegacyTimeline(legacyTimeline, limit)),
() ->
groupRoleRelDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
GroupRoleRelMapper.class,
mapper ->
mapper.deleteGroupRoleRelMetasByLegacyTimeline(legacyTimeline, limit)));
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/JobTemplateMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/JobTemplateMetaService.java
index c8c61cb51f..a042d8ba70 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/JobTemplateMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/JobTemplateMetaService.java
@@ -117,7 +117,7 @@ public class JobTemplateMetaService {
mapper.softDeleteJobMetaByMetalakeAndTemplate(metalakeName, jobTemplateName)),
() ->
result.set(
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
JobTemplateMetaMapper.class,
mapper ->
mapper.softDeleteJobTemplateMetaByMetalakeAndName(
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelMetaService.java
index 2a5db664c7..58c46d6a01 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelMetaService.java
@@ -137,7 +137,7 @@ public class ModelMetaService {
// delete model meta
() ->
modelDeletedCount.set(
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
ModelMetaMapper.class,
mapper ->
mapper.softDeleteModelMetaBySchemaIdAndModelName(schemaId, ident.name()))),
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelVersionMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelVersionMetaService.java
index 085ae844dd..0c3caa52b8 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelVersionMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelVersionMetaService.java
@@ -205,7 +205,7 @@ public class ModelVersionMetaService {
// Delete model version relations first
() ->
modelVersionDeletedCount.set(
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
ModelVersionMetaMapper.class,
mapper -> {
if (isVersionNumber) {
@@ -245,13 +245,13 @@ public class ModelVersionMetaService {
SessionUtils.doMultipleWithCommit(
() ->
modelVersionDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
ModelVersionMetaMapper.class,
mapper ->
mapper.deleteModelVersionMetasByLegacyTimeline(legacyTimeline, limit)),
() ->
modelVersionAliasRelDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
ModelVersionAliasRelMapper.class,
mapper ->
mapper.deleteModelVersionAliasRelsByLegacyTimeline(legacyTimeline, limit)));
@@ -334,7 +334,7 @@ public class ModelVersionMetaService {
if (isModelVersionUriUpdated) {
// delete old model version POs first
updateResult.addAndGet(
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
ModelVersionMetaMapper.class,
mapper -> {
if (isVersionNumber) {
@@ -355,7 +355,7 @@ public class ModelVersionMetaService {
} else {
// update model version POs directly
updateResult.addAndGet(
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
ModelVersionMetaMapper.class,
mapper ->
mapper.updateModelVersionMeta(
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/PolicyMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/PolicyMetaService.java
index add500f5b1..af45cc0c85 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/PolicyMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/PolicyMetaService.java
@@ -175,13 +175,13 @@ public class PolicyMetaService {
SessionUtils.doMultipleWithCommit(
() ->
policyMetaDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
PolicyMetaMapper.class,
mapper ->
mapper.softDeletePolicyByMetalakeAndPolicyName(metalakeName, ident.name())),
() ->
policyVersionDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
PolicyVersionMapper.class,
mapper ->
mapper.softDeletePolicyVersionByMetalakeAndPolicyName(
@@ -203,7 +203,7 @@ public class PolicyMetaService {
metalakeId, metadataObject.fullName(), metadataObject.type());
PolicyPOs =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
PolicyMetadataObjectRelMapper.class,
mapper ->
mapper.listPolicyPOsByMetadataObjectIdAndType(
@@ -350,7 +350,7 @@ public class PolicyMetaService {
// Fetch all the policies associated with the metadata object after the
operation.
List<PolicyPO> policyPOs =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
PolicyMetadataObjectRelMapper.class,
mapper ->
mapper.listPolicyPOsByMetadataObjectIdAndType(
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
index c75462005a..9c3f324966 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
@@ -336,23 +336,23 @@ public class RoleMetaService {
SessionUtils.doMultipleWithCommit(
() ->
roleDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
RoleMetaMapper.class,
mapper ->
mapper.deleteRoleMetasByLegacyTimeline(legacyTimeline, limit)),
() ->
userRoleRelDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
UserRoleRelMapper.class,
mapper ->
mapper.deleteUserRoleRelMetasByLegacyTimeline(legacyTimeline, limit)),
() ->
groupRoleRelDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
GroupRoleRelMapper.class,
mapper ->
mapper.deleteGroupRoleRelMetasByLegacyTimeline(legacyTimeline, limit)),
() ->
securableObjectsCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
SecurableObjectMapper.class,
mapper ->
mapper.deleteSecurableObjectsByLegacyTimeline(legacyTimeline, limit)));
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TableColumnMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TableColumnMetaService.java
index 0fb78573be..7391dffd25 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TableColumnMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TableColumnMetaService.java
@@ -100,7 +100,7 @@ public class TableColumnMetaService {
boolean deleteColumnsByTableId(Long tableId) {
// deleteColumns will be done in deleteTable transaction, so we don't do
commit here.
Integer result =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TableColumnMapper.class, mapper ->
mapper.softDeleteColumnsByTableId(tableId));
return result > 0;
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TableMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TableMetaService.java
index 4d2a979342..190f3b8903 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TableMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TableMetaService.java
@@ -180,7 +180,7 @@ public class TableMetaService {
SessionUtils.doMultipleWithCommit(
() ->
updateResult.set(
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TableMetaMapper.class,
mapper -> mapper.updateTableMeta(newTablePO,
oldTablePO))),
() -> {
@@ -217,7 +217,7 @@ public class TableMetaService {
SessionUtils.doMultipleWithCommit(
() ->
deleteResult.set(
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TableMetaMapper.class,
mapper -> mapper.softDeleteTableMetasByTableId(tableId))),
() -> {
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
index 3b2c6d42e2..c5481357df 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/TagMetaService.java
@@ -140,13 +140,13 @@ public class TagMetaService {
SessionUtils.doMultipleWithCommit(
() ->
tagDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TagMetaMapper.class,
mapper ->
mapper.softDeleteTagMetaByMetalakeAndTagName(metalakeName, ident.name())),
() ->
tagMetadataObjectRelDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TagMetadataObjectRelMapper.class,
mapper ->
mapper.softDeleteTagMetadataObjectRelsByMetalakeAndTagName(
@@ -169,7 +169,7 @@ public class TagMetaService {
metalakeId, metadataObject.fullName(), metadataObject.type());
tagPOs =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TagMetadataObjectRelMapper.class,
mapper ->
mapper.listTagPOsByMetadataObjectIdAndType(
@@ -336,7 +336,7 @@ public class TagMetaService {
// Fetch all the tags associated with the metadata object after the
operation.
List<TagPO> tagPOs =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TagMetadataObjectRelMapper.class,
mapper ->
mapper.listTagPOsByMetadataObjectIdAndType(
@@ -359,12 +359,12 @@ public class TagMetaService {
SessionUtils.doMultipleWithCommit(
() ->
tagDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TagMetaMapper.class,
mapper ->
mapper.deleteTagMetasByLegacyTimeline(legacyTimeline, limit)),
() ->
tagMetadataObjectRelDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
TagMetadataObjectRelMapper.class,
mapper ->
mapper.deleteTagEntityRelsByLegacyTimeline(legacyTimeline, limit)));
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
index a8991da14b..98e14fb734 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
@@ -285,12 +285,12 @@ public class UserMetaService {
SessionUtils.doMultipleWithCommit(
() ->
userDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
UserMetaMapper.class,
mapper ->
mapper.deleteUserMetasByLegacyTimeline(legacyTimeline, limit)),
() ->
userRoleRelDeletedCount[0] =
- SessionUtils.doWithoutCommitAndFetchResult(
+ SessionUtils.getWithoutCommit(
UserRoleRelMapper.class,
mapper ->
mapper.deleteUserRoleRelMetasByLegacyTimeline(legacyTimeline, limit)));
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/session/SqlSessions.java
b/core/src/main/java/org/apache/gravitino/storage/relational/session/SqlSessions.java
index def9c5e43f..03d6608a65 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/session/SqlSessions.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/session/SqlSessions.java
@@ -20,8 +20,11 @@
package org.apache.gravitino.storage.relational.session;
import com.google.common.annotations.VisibleForTesting;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.TransactionIsolationLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* SqlSessions is a utility class to maintain the MyBatis's {@link SqlSession}
object. It is a
@@ -29,7 +32,10 @@ import org.apache.ibatis.session.TransactionIsolationLevel;
* methods to commit, rollback and close the {@link SqlSession} object.
*/
public final class SqlSessions {
+ private static final Logger LOG = LoggerFactory.getLogger(SqlSessions.class);
private static final ThreadLocal<SqlSession> sessions = new ThreadLocal<>();
+ private static final ThreadLocal<AtomicInteger> sessionCount =
+ ThreadLocal.withInitial(() -> new AtomicInteger(0));
private SqlSessions() {}
@@ -38,9 +44,15 @@ public final class SqlSessions {
return sessions;
}
+ @VisibleForTesting
+ static Integer getSessionCount() {
+ return sessionCount.get().get();
+ }
+
/**
* Get the SqlSession object. If the SqlSession object is not present in the
thread local, then
- * create a new SqlSession object and set it in the thread local.
+ * create a new SqlSession object and set it in the thread local. This
method also increments the
+ * session count.
*
* @return SqlSession object from the thread local storage.
*/
@@ -52,8 +64,8 @@ public final class SqlSessions {
.getSqlSessionFactory()
.openSession(TransactionIsolationLevel.READ_COMMITTED);
sessions.set(sqlSession);
- return sqlSession;
}
+ sessionCount.get().incrementAndGet();
return sqlSession;
}
@@ -62,15 +74,7 @@ public final class SqlSessions {
* thread local storage.
*/
public static void commitAndCloseSqlSession() {
- SqlSession sqlSession = sessions.get();
- if (sqlSession != null) {
- try {
- sqlSession.commit();
- sqlSession.close();
- } finally {
- sessions.remove();
- }
- }
+ handleSessionClose(true /* commit */, false /* rollback */);
}
/**
@@ -78,37 +82,58 @@ public final class SqlSessions {
* thread local storage.
*/
public static void rollbackAndCloseSqlSession() {
- SqlSession sqlSession = sessions.get();
- if (sqlSession != null) {
- try {
- sqlSession.rollback();
- sqlSession.close();
- } finally {
- sessions.remove();
- }
- }
+ handleSessionClose(false /* commit */, true /* rollback */);
}
/** Close the SqlSession object and remove it from the thread local storage.
*/
public static void closeSqlSession() {
- SqlSession sqlSession = sessions.get();
- if (sqlSession != null) {
- try {
- sqlSession.close();
- } finally {
- sessions.remove();
- }
- }
+ handleSessionClose(false /* commit */, false /* rollback */);
}
/**
- * Get the Mapper object from the SqlSession object.
+ * Get the Mapper object from the SqlSession object. This method will open a
session if one is not
+ * already opened.
*
* @param <T> the type of the mapper interface.
* @param className the class name of the Mapper object.
* @return the Mapper object.
*/
public static <T> T getMapper(Class<T> className) {
+ // getSqlSession() is called to ensure a session exists and increment the
count.
return getSqlSession().getMapper(className);
}
+
+ private static void handleSessionClose(boolean commit, boolean rollback) {
+ SqlSession sqlSession = sessions.get();
+ if (sqlSession == null) {
+ return;
+ }
+
+ int count = sessionCount.get().decrementAndGet();
+ if (count == 0) {
+ try {
+ if (commit) {
+ sqlSession.commit();
+ } else if (rollback) {
+ sqlSession.rollback();
+ }
+ } finally {
+ try {
+ // Ensure the session is always closed
+ sqlSession.close();
+ } finally {
+ // Ensure ThreadLocal is always cleaned up
+ sessions.remove();
+ sessionCount.remove();
+ }
+ }
+ } else if (count < 0) {
+ // This should not happen if the session management is correct.
+ // Reset the count and remove the session to avoid further issues.
+ LOG.warn(
+ "Session count is negative: {}. Resetting session count and removing
session.", count);
+ sessions.remove();
+ sessionCount.remove();
+ }
+ }
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/utils/SessionUtils.java
b/core/src/main/java/org/apache/gravitino/storage/relational/utils/SessionUtils.java
index 5138b4dcbb..752d89533d 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/utils/SessionUtils.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/utils/SessionUtils.java
@@ -23,7 +23,6 @@ import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Function;
import org.apache.gravitino.storage.relational.session.SqlSessions;
-import org.apache.ibatis.session.SqlSession;
/**
* This class provides utility methods to perform database operations with
MyBatis mappers in the
@@ -33,116 +32,78 @@ public class SessionUtils {
private SessionUtils() {}
/**
- * This method is used to perform a database operation with a commit. If the
operation fails, the
- * transaction will roll back.
- *
- * @param mapperClazz mapper class to be used for the operation
- * @param consumer the operation to be performed with the mapper
- * @param <T> the type of the mapper
+ * Performs a database operation with a commit. Manages the full transaction
lifecycle. Can be
+ * nested within other transactions.
*/
public static <T> void doWithCommit(Class<T> mapperClazz, Consumer<T>
consumer) {
- try (SqlSession session = SqlSessions.getSqlSession()) {
- try {
- T mapper = SqlSessions.getMapper(mapperClazz);
- consumer.accept(mapper);
- SqlSessions.commitAndCloseSqlSession();
- } catch (Exception e) {
- SqlSessions.rollbackAndCloseSqlSession();
- throw e;
- }
+ try {
+ T mapper = SqlSessions.getMapper(mapperClazz);
+ consumer.accept(mapper);
+ SqlSessions.commitAndCloseSqlSession();
+ } catch (Exception e) {
+ SqlSessions.rollbackAndCloseSqlSession();
+ throw e;
}
}
/**
- * This method is used to perform a database operation with a commit and
fetch the result. If the
- * operation fails, the transaction will roll back.
- *
- * @param mapperClazz mapper class to be used for the operation
- * @param func the operation to be performed with the mapper
- * @return the result of the operation
- * @param <T> the type of the mapper
- * @param <R> the type of the result
+ * Performs a database operation with a commit and fetches a result. Manages
the full transaction
+ * lifecycle. Can be nested within other transactions.
*/
public static <T, R> R doWithCommitAndFetchResult(Class<T> mapperClazz,
Function<T, R> func) {
- try (SqlSession session = SqlSessions.getSqlSession()) {
- try {
- T mapper = SqlSessions.getMapper(mapperClazz);
- R result = func.apply(mapper);
- SqlSessions.commitAndCloseSqlSession();
- return result;
- } catch (Exception e) {
- SqlSessions.rollbackAndCloseSqlSession();
- throw e;
- }
+ try {
+ T mapper = SqlSessions.getMapper(mapperClazz);
+ R result = func.apply(mapper);
+ SqlSessions.commitAndCloseSqlSession();
+ return result;
+ } catch (Exception e) {
+ SqlSessions.rollbackAndCloseSqlSession();
+ throw e;
}
}
/**
- * This method is used to perform a database operation without a commit and
fetch the result. If
- * the operation fails, will throw the RuntimeException.
- *
- * @param mapperClazz mapper class to be used for the operation
- * @param func the operation to be performed with the mapper
- * @return the result of the operation
- * @param <T> the type of the mapper
- * @param <R> the type of the result
+ * Performs a read-only database operation without a commit. Can be used
standalone or nested
+ * within other transactions.
*/
- public static <T, R> R doWithoutCommitAndFetchResult(Class<T> mapperClazz,
Function<T, R> func) {
- T mapper = SqlSessions.getMapper(mapperClazz);
- return func.apply(mapper);
+ public static <T, R> R getWithoutCommit(Class<T> mapperClazz, Function<T, R>
func) {
+ try {
+ T mapper = SqlSessions.getMapper(mapperClazz);
+ return func.apply(mapper);
+ } finally {
+ // This will decrement the counter, the session is closed only when the
counter is 0.
+ SqlSessions.closeSqlSession();
+ }
}
/**
- * This method is used to perform a database operation without a commit. If
the operation fails,
- * will throw the RuntimeException.
- *
- * @param mapperClazz mapper class to be used for the operation
- * @param consumer the operation to be performed with the mapper
- * @param <T> the type of the mapper
+ * Performs a database operation without a commit. Can be used standalone or
nested within other
+ * transactions. This method is for operations that do not return a result.
*/
public static <T> void doWithoutCommit(Class<T> mapperClazz, Consumer<T>
consumer) {
- T mapper = SqlSessions.getMapper(mapperClazz);
- consumer.accept(mapper);
- }
-
- /**
- * This method is used to perform a database operation without a commit and
fetch the result. If
- * the operation fails, will throw a RuntimeException.
- *
- * @param mapperClazz mapper class to be used for the operation
- * @param func the operation to be performed with the mapper
- * @return the result of the operation
- * @param <T> the type of the mapper
- * @param <R> the type of the result
- */
- public static <T, R> R getWithoutCommit(Class<T> mapperClazz, Function<T, R>
func) {
- try (SqlSession session = SqlSessions.getSqlSession()) {
- try {
- T mapper = SqlSessions.getMapper(mapperClazz);
- return func.apply(mapper);
- } catch (Exception e) {
- throw e;
- } finally {
- SqlSessions.closeSqlSession();
- }
+ try {
+ T mapper = SqlSessions.getMapper(mapperClazz);
+ consumer.accept(mapper);
+ } finally {
+ // This will decrement the counter, the session is closed only when the
counter is 0.
+ SqlSessions.closeSqlSession();
}
}
/**
- * This method is used to perform multiple database operations with a
commit. If any of the
- * operations fail, the transaction will totally roll back.
- *
- * @param operations the operations to be performed
+ * Performs multiple database operations within a single commit. Manages the
full transaction
+ * lifecycle.
*/
public static void doMultipleWithCommit(Runnable... operations) {
- try (SqlSession session = SqlSessions.getSqlSession()) {
- try {
- Arrays.stream(operations).forEach(Runnable::run);
- SqlSessions.commitAndCloseSqlSession();
- } catch (Exception e) {
- SqlSessions.rollbackAndCloseSqlSession();
- throw e;
- }
+ // This method acts as the outermost transaction boundary.
+ // It increments the session count once.
+ SqlSessions.getSqlSession();
+ try {
+ Arrays.stream(operations).forEach(Runnable::run);
+ SqlSessions.commitAndCloseSqlSession();
+ } catch (Exception e) {
+ SqlSessions.rollbackAndCloseSqlSession();
+ throw e;
}
}
}
diff --git
a/core/src/test/java/org/apache/gravitino/storage/relational/session/TestSqlSession.java
b/core/src/test/java/org/apache/gravitino/storage/relational/session/TestSqlSession.java
index 9942d2fe00..daad141318 100644
---
a/core/src/test/java/org/apache/gravitino/storage/relational/session/TestSqlSession.java
+++
b/core/src/test/java/org/apache/gravitino/storage/relational/session/TestSqlSession.java
@@ -134,23 +134,29 @@ public class TestSqlSession {
public void testOpenAndCloseSqlSession() {
SqlSession session = SqlSessions.getSqlSession();
assertNotNull(session);
+ assertEquals(1, SqlSessions.getSessionCount());
SqlSessions.closeSqlSession();
assertNull(SqlSessions.getSessions().get());
+ assertEquals(0, SqlSessions.getSessionCount());
}
@Test
public void testOpenAndCommitAndCloseSqlSession() {
SqlSession session = SqlSessions.getSqlSession();
assertNotNull(session);
+ assertEquals(1, SqlSessions.getSessionCount());
SqlSessions.commitAndCloseSqlSession();
assertNull(SqlSessions.getSessions().get());
+ assertEquals(0, SqlSessions.getSessionCount());
}
@Test
public void testOpenAndRollbackAndCloseSqlSession() {
SqlSession session = SqlSessions.getSqlSession();
assertNotNull(session);
+ assertEquals(1, SqlSessions.getSessionCount());
SqlSessions.rollbackAndCloseSqlSession();
assertNull(SqlSessions.getSessions().get());
+ assertEquals(0, SqlSessions.getSessionCount());
}
}