Skip to content

Commit c49db4d

Browse files
committed
Release v0.0.12. Add rollback logic.
1 parent f5aae00 commit c49db4d

7 files changed

+155
-27
lines changed

example_decorator.py

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
user="mybatis", # MySQL 用户名
77
password="mybatis", # MySQL 密码
88
database="mybatis", # 需要连接的数据库,
9+
autocommit=False
910
)
1011

1112
mb = Mybatis(conn, "mapper", cache_memory_limit=50*1024*1024)

mapper/test_db_rollback.xml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3+
<mapper>
4+
<insert id="testDBRollbackInsert">
5+
INSERT INTO fruits2 (name, category, price) VALUES ('Candy', 'B', 500)
6+
</insert>
7+
<delete id="testDBRollbackDelete">
8+
DELETE FROM fruits2 WHERE id=1
9+
</delete>
10+
<update id="testDBRollbackUpdate">
11+
UPDATE fruits2 SET name='Candy' WHERE id=1
12+
</update>
13+
</mapper>

mybatis/mybatis.py

+51-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from typing import Optional, Dict, List
22

3+
import mysql.connector.errors
4+
35
from .mapper_manager import MapperManager
46
from .cache import Cache, CacheKey
57

@@ -98,10 +100,14 @@ def update(self, id:str, params:dict) -> int:
98100
res = self.cache.clear()
99101

100102
with self.conn.cursor(prepared=True) as cursor:
101-
cursor.execute(sql, param_list)
102-
affected_rows = cursor.rowcount
103-
self.conn.commit()
104-
return affected_rows
103+
try:
104+
cursor.execute(sql, param_list)
105+
affected_rows = cursor.rowcount
106+
self.conn.commit()
107+
return affected_rows
108+
except mysql.connector.errors.Error as e:
109+
self.conn.rollback()
110+
raise e
105111

106112
def delete(self, id:str, params:dict) -> int:
107113
'''
@@ -114,10 +120,14 @@ def delete(self, id:str, params:dict) -> int:
114120
res = self.cache.clear()
115121

116122
with self.conn.cursor(prepared=True) as cursor:
117-
cursor.execute(sql, param_list)
118-
affected_rows = cursor.rowcount
119-
self.conn.commit()
120-
return affected_rows
123+
try:
124+
cursor.execute(sql, param_list)
125+
affected_rows = cursor.rowcount
126+
self.conn.commit()
127+
return affected_rows
128+
except mysql.connector.errors.Error as e:
129+
self.conn.rollback()
130+
raise e
121131

122132
def insert(self, id:str, params:dict) -> int:
123133
'''
@@ -130,10 +140,14 @@ def insert(self, id:str, params:dict) -> int:
130140
res = self.cache.clear()
131141

132142
with self.conn.cursor(prepared=True) as cursor:
133-
cursor.execute(sql, param_list)
134-
self.conn.commit()
135-
last_id = cursor.lastrowid
136-
return last_id
143+
try:
144+
cursor.execute(sql, param_list)
145+
self.conn.commit()
146+
last_id = cursor.lastrowid
147+
return last_id
148+
except mysql.connector.errors.Error as e:
149+
self.conn.rollback()
150+
raise e
137151

138152

139153
def SelectOne(self, unparsed_sql:str) -> Optional[Dict]:
@@ -220,10 +234,14 @@ def wrapper(*args, **kwargs):
220234
res = self.cache.clear()
221235

222236
with self.conn.cursor(prepared=True) as cursor:
223-
cursor.execute(sql, param_list)
224-
self.conn.commit()
225-
last_id = cursor.lastrowid
226-
return last_id
237+
try:
238+
cursor.execute(sql, param_list)
239+
self.conn.commit()
240+
last_id = cursor.lastrowid
241+
return last_id
242+
except mysql.connector.errors.Error as e:
243+
self.conn.rollback()
244+
raise e
227245
return wrapper
228246
return decorator
229247

@@ -240,10 +258,15 @@ def wrapper(*args, **kwargs):
240258
res = self.cache.clear()
241259

242260
with self.conn.cursor(prepared=True) as cursor:
243-
cursor.execute(sql, param_list)
244-
affected_rows = cursor.rowcount
245-
self.conn.commit()
246-
return affected_rows
261+
try:
262+
cursor.execute(sql, param_list)
263+
affected_rows = cursor.rowcount
264+
self.conn.commit()
265+
return affected_rows
266+
except mysql.connector.errors.Error as e:
267+
self.conn.rollback()
268+
raise e
269+
247270
return wrapper
248271
return decorator
249272

@@ -260,10 +283,14 @@ def wrapper(*args, **kwargs):
260283
res = self.cache.clear()
261284

262285
with self.conn.cursor(prepared=True) as cursor:
263-
cursor.execute(sql, param_list)
264-
affected_rows = cursor.rowcount
265-
self.conn.commit()
266-
return affected_rows
286+
try:
287+
cursor.execute(sql, param_list)
288+
affected_rows = cursor.rowcount
289+
self.conn.commit()
290+
return affected_rows
291+
except mysql.connector.errors.Error as e:
292+
self.conn.rollback()
293+
raise e
267294

268295
return wrapper
269296

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='mybatis',
5-
version='0.0.11',
5+
version='0.0.12',
66
description='A python ORM like mybatis.',
77
long_description=open('README.md').read(),
88
long_description_content_type='text/markdown', # 如果你使用的是Markdown格式的README

test/test_db_rollback.py

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import pytest
2+
import mysql.connector
3+
4+
from mybatis import Mybatis
5+
6+
7+
@pytest.fixture(scope="function")
8+
def db_connection():
9+
# 配置数据库连接
10+
connection = mysql.connector.connect(
11+
host="localhost",
12+
user="mybatis",
13+
password="mybatis",
14+
database="mybatis",
15+
autocommit=False,
16+
)
17+
connection.start_transaction()
18+
cursor = connection.cursor()
19+
cursor.execute("DROP TABLE IF EXISTS fruits")
20+
create_table_sql = '''CREATE TABLE IF NOT EXISTS fruits (
21+
id INT AUTO_INCREMENT PRIMARY KEY,
22+
name VARCHAR(100),
23+
category VARCHAR(100),
24+
price int)
25+
'''
26+
# 在测试开始前准备数据
27+
cursor.execute(create_table_sql)
28+
cursor.execute("INSERT INTO fruits (name, category, price) VALUES ('Alice', 'A', 100)")
29+
cursor.execute("INSERT INTO fruits (name, category, price) VALUES ('Bob', 'B', 200)")
30+
connection.commit()
31+
32+
# 提供数据库连接给测试用例
33+
yield connection
34+
35+
# 清理数据和关闭连接
36+
connection.close()
37+
38+
def test_db_rollback_error_table(db_connection):
39+
mb = Mybatis(db_connection, "mapper")
40+
@mb.Insert("INSERT INTO fruits2 (name, category, price) VALUES ('Candy', 'B', 500)")
41+
def insert():
42+
pass
43+
44+
try:
45+
insert()
46+
except mysql.connector.errors.Error as err:
47+
assert True
48+
49+
@mb.Delete("DELETE FROM fruits2 WHERE id=1")
50+
def delete():
51+
pass
52+
53+
try:
54+
delete()
55+
except mysql.connector.errors.Error as err:
56+
assert True
57+
58+
@mb.Delete("UPDATE fruits2 SET name='Candy' WHERE id=1")
59+
def update():
60+
pass
61+
62+
try:
63+
update()
64+
except mysql.connector.errors.Error as err:
65+
assert True
66+
67+
def test_db_rollback_error_table2(db_connection):
68+
mb = Mybatis(db_connection, "mapper")
69+
try:
70+
mb.insert("testDBRollbackInsert", {})
71+
except mysql.connector.errors.Error as err:
72+
assert True
73+
74+
try:
75+
mb.delete("testDBRollbackDelete", {})
76+
except mysql.connector.errors.Error as err:
77+
assert True
78+
79+
try:
80+
mb.update("testDBRollbackUpdate", {})
81+
except mysql.connector.errors.Error as err:
82+
assert True

test/test_mybatis.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ def db_connection():
1111
host="localhost",
1212
user="mybatis",
1313
password="mybatis",
14-
database="mybatis"
14+
database="mybatis",
15+
autocommit=False,
1516
)
17+
connection.start_transaction()
1618
cursor = connection.cursor()
1719
cursor.execute("DROP TABLE IF EXISTS fruits")
1820
create_table_sql = '''CREATE TABLE IF NOT EXISTS fruits (

test/test_mybatis_decorator.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ def db_connection():
1111
host="localhost",
1212
user="mybatis",
1313
password="mybatis",
14-
database="mybatis"
14+
database="mybatis",
15+
autocommit=False,
1516
)
17+
connection.start_transaction()
1618
cursor = connection.cursor()
1719
cursor.execute("DROP TABLE IF EXISTS fruits")
1820
create_table_sql = '''CREATE TABLE IF NOT EXISTS fruits (
@@ -26,6 +28,7 @@ def db_connection():
2628
cursor.execute("INSERT INTO fruits (name, category, price) VALUES ('Alice', 'A', 100)")
2729
cursor.execute("INSERT INTO fruits (name, category, price) VALUES ('Bob', 'B', 200)")
2830
connection.commit()
31+
cursor.close()
2932

3033
# 提供数据库连接给测试用例
3134
yield connection

0 commit comments

Comments
 (0)