Python中Mysqldb的使用以及事务的支持-pybatis首次露面-pybatis的准备阶段(十)

http://zetcode.com/db/mysqlpython/

这个地址中有一些关于mysqldb模块的使用介绍。

其中关键一点的是事务支持。

For databases that support transactions, the Python interface silently starts a transaction when the cursor is created. The commit() method commits the updates made using that cursor, and the rollback() method discards them.


上面这句话说的比较好。在py的mysqldb中,一旦创建了一个cursor,那么就默认创建了一个事务。直到提交事务为止,数据库的数据才会进行更改。但是对于不支持事务的数据库来说,事务不起作用。

------------------------------------------------------------

上面是mysqldb的事务支持。那么,我自己的pybatis要怎么实现呢?

目前是这样的:

对于单一的查询,开启一个数据库连接,执行sql,然后提交事务,关闭cursor和conn即可。

但是对于用户需要全局事务来说,是这样的:

把所有的查询都放在同一个connection中。在最后的时候再使用conn.commit()进行提交。

贴一下临时的transactionmanager的代码:

# -*- coding:utf-8 -*-
'''
Created on 2013-3-10

@author: naughty
'''
from _mysql_exceptions import IntegrityError
from com.util.Data2Object import Data2Object
from com.util.SqlPreprocessing import processSql
import MySQLdb as mdb

class TransactionManager(object):
    '''
    handles all transaction and db query
    '''
    def __init__(self):
        '''
        初始化的时候传入一个连接
        '''
        self.conn = mdb.connect(host='localhost', user='', passwd='', db='test')
        #=======================================================================
        # 初始化一个cursor
        #=======================================================================
        self.cursor = self.conn.cursor()
        
    def startTransaction(self):
        '''
        For databases that support transactions, 
        the Python interface silently starts a transaction when the cursor is created.
        so we do nothing here.
        '''
        pass
    def commitTransaction(self):
        '''
        提交事务
        '''
        self.cursor.close()
        self.conn.commit()
    def endTransaction(self):
        '''
        结束事务
        '''
        pass
    def rollbackTransaction(self):
        '''
        回滚事务
        '''
        self.cursor.close()
        self.conn.rollback()
        
    def queryInsert(self, sqlid, inputObject):
        '''
        查询插入
        '''
        #=======================================================================
        # resultclasstype参数在没有返回值的时候用不到
        #=======================================================================
        sql , resultclasstype = processSql(sqlid, inputObject)
        try:
            var=self.cursor.execute(sql)
            return var
        except IntegrityError:
            return -1
        
    def queryUpdate(self, sqlid, inputObject):
        '''
        查询更新
        '''
        self.queryInsert(sqlid, inputObject)
    def queryDelete(self, sqlid, inputObject):
        '''
        查询删除
        '''
        self.queryInsert(sqlid, inputObject)

    def queryForObject(self, sqlid, inputObject):
        '''
        查询并返回一个对象
        '''
        sql, resultclasstype = processSql(sqlid, inputObject)
        self.cursor.execute(sql)
        objList = Data2Object.data2object(self.cursor, resultclasstype)
        if len(objList) == 0:
            return None
        elif len(objList) == 1:
            return objList[0]
        else:
            raise Exception('query for one object, but get many.');
        
    def queryForList(self, sqlid, inputObject):
        '''
        查询并返回一个列表
        '''
        sql , resultclasstype = processSql(sqlid, inputObject)
        self.cursor.execute(sql)
        objList = Data2Object.data2object(self.cursor, resultclasstype)
        return objList
    


上面的代码只有在commitTransaction的时候才会提交事务。【rollbackTransaction的时候,最后还需要关闭连接。上面的代码忘记关闭了】

看下面的测试用例:

# -*- coding:utf-8 -*-
'''
Created on 2013-3-5

@author: naughty
'''
from com.domain import beans
from com.domain.TransactionManager import TransactionManager
from com.util.DBExecuteCenter import queryForObject, queryInsert, queryUpdate, \
    queryDelete

if __name__ == '__main__':
    s = beans.Student()
    s.age = '1'
    s.name = 'zoer'
    s.score = 11
    t = TransactionManager()
    try:
        t.startTransaction()
        num = t.queryDelete('del', s)
        print num
        s.score = 22
        num = t.queryDelete('del', s)
        print num
        t.commitTransaction()
    except:
        t.rollbackTransaction()

    print 'end'


用例中,尝试删除score是11和22的学生。但是,由于22是有外键约束的【我人为添加的一个外键约束】,所以删除22 的学生的时候会失败。这样,上面的代码在执行到删除22的时候由于抛出异常,就会去回滚事务。

--------------------------------

上面展示的是“大事务”控制。使用TransactionManager来操作。

下面展示一下单个操作时候的事务控制。

单个事务控制是放在 中进行解决的。

# -*- coding:utf-8 -*-
'''
Created on 2013-3-6

@author: naughty
'''

from Data2Object import Data2Object
from com.util.SqlPreprocessing import processSql
import MySQLdb as mdb
import com.pybatis.Global

def queryForObject(sqlid, inputObject=None):
    '''
    查询并返回对象
    '''
    #===========================================================================
    # 每次都新建连接
    #===========================================================================
    conn = mdb.connect(host='localhost', user='', passwd='', db='test')
    cursor = conn.cursor()
    sql, resultclasstype = processSql(sqlid, inputObject)
    try:
        cursor.execute(sql)
    except:
        cursor.close()
        conn.rollback()
        conn.close()
    else:
        objList = Data2Object.data2object(cursor, resultclasstype)
        cursor.close()
        if len(objList) == 0:
            conn.close()
            return None
        elif len(objList) == 1:
            conn.close()
            return objList[0]
        else:
            conn.close()
            raise Exception('query for one object, but get many.');

def queryForList(sqlid, inputObject=None):
    '''
    查询并返回列表
    '''
    #===========================================================================
    # 每次都新建连接
    #===========================================================================
    conn = mdb.connect(host='localhost', user='', passwd='', db='test')
    cursor = conn.cursor()
    sql , resultclasstype = processSql(sqlid, inputObject)
    try:
        cursor.execute(sql)
    except:
        cursor.close()
        conn.rollback()
        conn.close()
    else:
        objList = Data2Object.data2object(cursor, resultclasstype)
        cursor.close()
        conn.close()
        return objList

def queryInsert(sqlid, inputObject=None):
    '''
    执行插入操作
    '''
    conn = mdb.connect(host='localhost', user='', passwd='', db='test')
    cursor = conn.cursor()
    sql , resultclasstype = processSql(sqlid, inputObject)
    try:
        count = cursor.execute(sql)
    except:
        #===========================================================================
        # 关闭游标
        #===========================================================================
        cursor.close()
        conn.rollback()
        conn.close()
        count = -1
    else:
        cursor.close()
        conn.commit()
        conn.close()
    return count

def queryUpdate(sqlid, inputObject=None):
    '''
    执行更新操作
    '''
    queryInsert(sqlid, inputObject)

def queryDelete(sqlid, inputObject=None):
    '''
    执行删除操作
    '''
    queryInsert(sqlid, inputObject)



单个事务控制的时候,把对数据库的操作放在了上面的这些函数中进行。具体看看queryInsert函数。操作是否成功需要根据返回值进行判断。如果返回值是-1,那么说明操作没有成功。相反则成功。

下面是一个使用的例子:

# -*- coding:utf-8 -*-
'''
Created on 2013-3-5

@author: naughty
'''
from com.domain import beans
from com.domain.TransactionManager import TransactionManager
from com.util.DBExecuteCenter import queryForObject, queryInsert, queryUpdate, \
    queryDelete

if __name__ == '__main__':
    s = beans.Student()
    s.age = '1'
    s.name = 'naughty'
    s.score = 11
    count=queryInsert('insert',s)
    print count
    print 'end'


例子中插入了一个学生信息。由于数据库中已经存在了name是naughty的学生【name是主键】,所以插入失败。print出来的值是-1。

--------------------------------------

上面基本展示了pybatis处理全局事务和单个事务的方法。其本质就是将所有的事务处理交给基本的connection去处理,pybatis只是使用了connection。

------------------------------------------

至此,pybatis的事务管理就告一个段落了【不是最终版本】。

接下来还需要一个数据库连接池。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值