From 8381d8cc36d78abaa83bafa0cedd4e64bb62fdde Mon Sep 17 00:00:00 2001
From: fasiondog <fasiondog@163.com>
Date: Sun, 6 Oct 2024 16:43:26 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20TransAction=EF=BC=8C?=
 =?UTF-8?q?=E4=B8=AD=E9=97=B4=E5=A4=84=E7=90=86=E5=BC=82=E5=B8=B8=E6=97=B6?=
 =?UTF-8?q?=EF=BC=8C=E8=87=AA=E5=8A=A8=E5=85=A8=E9=83=A8=E5=9B=9E=E6=BB=9A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../utilities/db_connect/AutoTransAction.h    | 46 +++++++++----------
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/AutoTransAction.h b/hikyuu_cpp/hikyuu/utilities/db_connect/AutoTransAction.h
index 2f5dac405..f14f7041c 100644
--- a/hikyuu_cpp/hikyuu/utilities/db_connect/AutoTransAction.h
+++ b/hikyuu_cpp/hikyuu/utilities/db_connect/AutoTransAction.h
@@ -16,15 +16,7 @@ namespace hku {
 
 /**
  * 自动事务处理,在代码块中自动启动事务,并在代码块退出后自动提交
- * @code
- *  try {
- *      AutoTransAction trans(driver);
- *      ...
- *  } catch (...) {
- *      driver->rollback();
- *  }
- * @endcode
- * @note 事务提交失败时,这里并没有处理回滚
+ * @note 当有多个数据更改是,如果在程序处理中间发送异常时,可能导致数据被部分提交
  * @ingroup DBConnect
  */
 class AutoTransAction {
@@ -63,9 +55,10 @@ class AutoTransAction {
 };
 
 /**
- * 手动事务处理,允许嵌套提交事务,退出时自动提交
+ * 手动事务处理,允许嵌套启动事务,必须手工启动和提交事务,自动退出时不会自动提交事务,而是回滚!
  * @details 必须有一次有效的手工启动事务,多次嵌套启动事务将被视为一次事务处理。
  *          手工提交一次事务后,如有新的事务处理,须再次手工启动事务。
+ * @note 嵌套时,可能发送内部事务已提交,但外部事务处理失败被回滚(仅回滚相应事务处理的部分)的情况
  * @ingroup DBConnect
  */
 class TransAction {
@@ -74,17 +67,23 @@ class TransAction {
      * 构造函数
      * @param driver 数据库连接指针
      */
-    explicit TransAction(const DBConnectPtr& driver) : m_driver(driver), m_committed(true) {}
+    explicit TransAction(const DBConnectPtr& driver)
+    : m_driver(driver), m_committed(false), m_started(true) {
+        HKU_CHECK(driver, "Null DBConnectPtr!");
+        m_driver->transaction();
+    }
 
     /** 析构函数 */
     ~TransAction() {
-        try {
-            if (!m_committed) {
-                m_driver->commit();
-            }
-        } catch (...) {
-            HKU_ERROR("Transaction commit failed!");
-            m_driver.reset();
+        // 如果没有主动提交事务,视为需要回滚
+        if (!m_started) {
+            HKU_WARN("Not manul begin transaction!");
+            return;
+        }
+
+        if (m_started && !m_committed) {
+            HKU_WARN("The transaction is rolled back!");
+            m_driver->rollback();
         }
     }
 
@@ -95,25 +94,23 @@ class TransAction {
 
     /** 启动事务 */
     void begin() {
-        if (m_committed) {
+        if (!m_started) {
             m_driver->transaction();
             m_committed = false;
+            m_started = true;
         }
     }
 
     /** 结束并提交事务 */
     void end() {
+        HKU_CHECK(m_started, "No transaction has started!");
         if (!m_committed) {
             m_driver->commit();
             m_committed = true;
+            m_started = false;
         }
     }
 
-    /** 回滚事务 */
-    void rollback() {
-        m_driver->rollback();
-    }
-
 private:
     TransAction() = delete;
     TransAction(const AutoTransAction&) = delete;
@@ -122,6 +119,7 @@ class TransAction {
 private:
     DBConnectPtr m_driver;
     bool m_committed;
+    bool m_started;
 };
 
 }  // namespace hku