Peewee使用之事务

上周学习了下基本的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()

    原文作者:liuchungui
    原文地址: https://www.jianshu.com/p/915b012a1d91
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞