您的位置:首页 > 编程语言 > Python开发

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

2013-03-11 17:34 609 查看
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的事务管理就告一个段落了【不是最终版本】。

接下来还需要一个数据库连接池。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: