上周学习了下基本的Peewee使用,知道了基本的增删改查和建数据库。不过,在项目中同步数据的时候,需要用到事务,于是赶紧补充了官方的Transactions,然后写个总结。
常用方法
Peewee实现事务最常用的方法是Database.atomic()
方法,非常简单,代码示例如下:
from xModels import XUser, database
with database.atomic() as transaction:
XUser.create(phone='184738373833', password='123456')
XUser.create(phone='184738373833332323232', password='123456')
当事务执行成功之后,它会自动commit()
,不需要我们手动调。当事务的代码块中抛出异常时,它会自动调用rollback()
。
例如,如果上面的phone设置了长度限制,第二条语句中的phone太长,那么就会抛出异常,然后上面结果是两个用户都不会被添加到数据库中。
注意:上面database是在xModels文件中MySQLDatabase的一个实例,创建方法如下:
from peewee import MySQLDatabase
database = MySQLDatabase('test', **{'charset': 'utf8', 'use_unicode': True, 'host': 'localhost', 'user': 'root', 'password': ''})
除了自动commit()
和rollback()
之外,我们也可以手动调用commit()
和rollback()
方法。
例如:
with database.atomic() as transaction:
XUser.create(phone='199999999999', password='123456')
transaction.commit()
XUser.create(phone='188888888888', password='123456')
transaction.rollback()
结果:手动调用了commit()
,phone为199999999999的用户成功添加,而188888888888因为rollback()
,不会被添加到数据库中。
两种使用方式
Peewee中实现事务有两种使用方式,一种是将atomic
当做Context manager
使用,另外一种将atomic
当修饰器使用。
Context manager
这种方式,就是我们前面已经使用过了,示例如下:
from xModels import XUser, database
with database.atomic() as transaction:
XUser.create(phone='184738373833', password='123456')
XUser.create(phone='184738373833332323232', password='123456')
修饰器
@database.atomic()
def create_user(phone, password):
XUser.create(phone=phone, password=password)
raise Exception('just a test')
create_user(phone='184738373833', password='383838')
上面,由于create_user()
中抛出了一个异常,修饰器中会执行rollback(),从而导致创建用户失败。
事务嵌套使用
Peewee中事务还可以进行嵌套,示例如下:
with database.atomic() as txn:
XUser.create(phone='18734738383')
with database.atomic() as nested_txn:
XUser.create(phone='1883328484')
当上面没有抛出异常时,两个用户同时被添加;当其中任何一条语句抛出异常时,两个用户都不会添加。
不过,它还是跟非嵌套有些区别的,看下面示例。
第一种情况,在嵌套事务中执行rollback(),代码如下:
with database.atomic() as txn:
XUser.create(phone='188888888')
with database.atomic() as nested_txn:
XUser.create(phone='199999999')
nested_txn.rollback()
结果:188888888
用户被添加,而199999999
不会被添加。
第二种情况,在外层的事务中执行rollback(),代码如下:
with database.atomic() as txn:
XUser.create(phone='188888888')
with database.atomic() as nested_txn:
XUser.create(phone='199999999')
txn.rollback()
结果:两个用户都不会被添加。
也就是说,外层的rollback()
会将嵌套中的事务也回滚,而嵌套中的事务不能回滚外层的内容。当然,这只是我的一个尝试,可能还有其他的不同,还需要再探索。
全手动实现事务
全手动实现事务使用的是Database.manual_commit()
方法,它也有Context manager
和修饰器
两种方式。
下面,我们使用Context manager
方式来实现前面说的atomic()
方法,示例代码如下:
with database.manual_commit():
database.begin() # 开始事务
try:
XUser.create(phone='188888888') # 添加用户
except:
database.rollback() # 执行rollback
raise
else:
try:
database.commit() # 没有发生异常,执行commit
except:
database.rollback() #commit发生异常时,执行rollback
raise
总结
Peewee实现事务最简单的方法就是atomic()
,它可以使用Context manager
和修饰器
两种方式,它也可以手动调用commit()
和rollback()
。