September 25, 2020
By: Dirk
clojure 事务管理
在日常开发中,后台开发不可避免都会与事务打交道,本文以实例的方式研究下事务嵌套及异常发生后捕获的行为。
准备数据库表
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)))