September 25, 2020
By: Dirk

clojure 事务管理

  1. 准备数据库表
  2. 准备插入sql语句
  3. 准备数据库操作方法
  4. 实例方式研究事务行为

在日常开发中,后台开发不可避免都会与事务打交道,本文以实例的方式研究下事务嵌套及异常发生后捕获的行为。

准备数据库表

CREATE TABLE `t_size` (
    `size_id` varchar(40) NOT NULL COMMENT '主键',
    `company_id` varchar(40)  COMMENT '所属公司',
    `category_id` varchar(40)  COMMENT '品类id',
    `body_type` varchar(40) COMMENT '版型 A型、B型、C型',
    `size_no` varchar(40) COMMENT '编号',
    `size_spec` varchar(40) COMMENT '规格'
    PRIMARY KEY (`size_id`) USING BTREE
    );

CREATE TABLE `t_pattern` (
  `pattern_id` varchar(40) COMMENT '主键',
  `company_id` varchar(40) COMMENT '公司id',
  `category_id` varchar(40) COMMENT '品类id',
  `pattern_name` varchar(100) COMMENT '版型名称'
  PRIMARY KEY (`pattern_id`) USING BTREE
  );

准备插入sql语句

-- :name demo-insert-size! :! :1
-- :doc 新增尺码
INSERT INTO t_size (size_id, company_id, category_id, body_type, size_no, size_spec)
VALUES (:size_id, :company_id, :category_id, :body_type, :size_no, :size_spec);

-- :name demo-insert-pattern! :! :1
-- :doc 新增尺码规格
INSERT INTO t_pattern (pattern_id, category_id, company_id, pattern_name, pattern_code)
VALUES (:pattern_id, :category_id, :company_id, :pattern_name, :pattern_code);

准备数据库操作方法

(defn- insert-pattern
  "新增尺码规格"
  []
  (demo-db/demo-insert-pattern!
     {:pattern_id (snowflake-id)
        :category_id "1"
        :company_id "demo-100"
        :pattern_name "测试"
        :pattern_code ""}))

(defn- insert-size
  "新增尺码"
  []
  (demo-db/demo-insert-size!
     {:size_id (snowflake-id)
        :company_id "demo-100"
        :category_id "1"
        :body_type "A"
        :size_no "72"
        :size_spec "170/72A"}))

(defn- insert-pattern-failure
  "新增尺码规格失败"
  []
  (demo-db/demo-insert-pattern!
     {:pattern_id (snowflake-id)
        :category_id "1"
        :company_id "demo-100"
        :pattern_name "测试"}))

(defn- insert-size-failure
  "新增尺码失败"
  []
  (demo-db/demo-insert-size!
     {:size_id (snowflake-id)
        :company_id "demo-100"

        :category_id "1"
        :body_type "A"
        :size_no "72"}))

(defn- insert-pattern-failure-with-catch
  "新增尺码规格失败异常捕获并处理"
  []
  (try
    (insert-pattern)
    (insert-pattern-failure)
    (catch Exception e (str "异常被捕获:" e))))

(defn- insert-pattern-failure-catch-and-throw
  "新增尺码规格失败异常捕获后throw"
  []
  (try
    (insert-pattern-failure)
    (catch Exception e (str "异常被捕获:" e)
     (throw e)
     #_(throw (RuntimeException. "RuntimeException")))))

实例方式研究事务行为

  • 不加事务,两条sql都正确 ==> 两条sql语句都插入成功
(defn test-transaction1
  "事务测试1"
  []
  (insert-pattern)
  (insert-size))
  • 不加事务,第1条语句正确,第2条语句错误 ==> 第1条语句正常插入,第2条语句插入失败
(defn test-transaction2
  "事务测试2"
  []
  (insert-pattern)
  (insert-size-failure))
  • 不加事务,第1条语句错误,第2条语句正确 ==> 两条语句都插入失败
(defn test-transaction3
  "事务测试3"
  []
  (insert-pattern-failure)
  (insert-size))
  • 加事务,第1条语句正确,第2条语句错误 ==> 两条语句都插入失败
(defn test-transaction4
  "事务测试4"
  []
  (conman.core/with-transaction [*db*]
    (insert-pattern)
    (insert-size-failure)))
  • 加事务,事务嵌套,第1条语句正确,第二组语句错误 ==> 两组语句都插入失败
(defn test-transaction5
  "事务测试5"
  []
  (conman.core/with-transaction [*db*]
    (insert-pattern)
    (test-transaction4)))
  • 第1条语句不加事务执行成功,第二组语句加事务且执行失败 ==> 第1条语句正常插入,第2条语句插入失败
(defn test-transaction6
  "事务测试6"
  []
  (insert-pattern)
  (test-transaction4))
  • 不加事务,第1条语句执行失败但捕获并处理异常,第2条语句正确 ==> 第1条语句插入失败,第2条语句插入成功
(defn test-transaction7
  "事务测试7"
  []
  (insert-pattern-failure-with-catch)
  (insert-size))
  • 添加事务,第1条语句执行失败但捕获并处理异常,第2条语句正确 ==> 第1条语句插入失败,第2条语句插入成功
(defn test-transaction8
  "事务测试8"
  []
  (conman.core/with-transaction [*db*]
    (insert-pattern-failure-with-catch)
    (insert-size)))
  • 不加事务,第1条语句执行失败捕获后throw,第2条语句正确 ==> 两条语句都插入失败
(defn test-transaction9
  "事务测试9"
  []
  (insert-pattern-failure-catch-and-throw)
  (insert-size))
  • 添加事务,第1条语句执行失败捕获后throw,第2条语句正确 ==> 两条语句都插入失败
(defn test-transaction10
  "事务测试10"
  []
  (conman.core/with-transaction [*db*]
    (insert-pattern-failure-catch-and-throw)
    (insert-size)))
Tags: transaction