Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5017268
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2015-07-05 20:49:38

D jango的ORM有一个很便捷的功能,其实也应该说是一个很基本的功能吧。就是在对一个model调用 save() 插入到数据库后,会将创建的自增id同步到当前model上。SQL中调用 INSERT 默认的返回值是插入的行数,就目前的应用来说,其实是一个没啥意义的返回值,所以Django的ORM能够处理好自增id的同步是一件很让人愉悦的事。

  不过没有使用Django,最近用的是Twisted提供的adbapi,如何获取自增id呢?

  如果是我力挺的PostgreSQL的话,很简单,给 INSERT 加上 RETURNING 语句就可以了:

  1. INSERT INTO distributors (did, dname)
  2. VALUES (DEFAULT, 'XYZ Widgets') RETURNING did;
不过MySQL呢?

  最近用了一阵子MySQL,只是从命令行自动补全这方面来说,就已经明显地感觉到和PostgreSQL的差距了。老实说真不知道为啥那么多人如此热爱深爱着MySQL……

  在StackOverflow上搜了一下,找到两种方法,要么是使用

  1. SELECT LAST_INSERT_ID();
或者是使用connector的 mysql_insert_id() 函数,这个对于Python中的 MySQLdb 来说就是connection的 insert_id() 函数,比如:

  1. conn = nnect(host='heaven', user='god',
  2.                        passwd='jesus', db='elysium')
  3. cursor = conn.cursor()
  4. cursor.execute('INSERT INTO account VALUES (%s, %s)',
  5.                ('satan', 'male or female, who knows'))
  6. new_id = conn.insert_id() # <= 就是这玩意儿

过程也还算简单,但是对于Twisted的adbapi来说,我们的活并没有结束。为啥呢?因为adbapi用的是线程池来管理MySQL的连接的,每次Query调用,都会从线程池中获取一个线程,然后将相应的事务defer到该线程来处理。其默认的事务是以单个SQL语句为划分的,所以说,对于MySQL这样在执行完后还需要做其他操作的需求来说,默认的接口是无法满足的。这儿我再吐一下槽,还是pg好啊……

  默认接口不够用,那我们就只能扩展它了。稍稍看一下adbapi的源代码我们可以发现,对于通常事务,adbapi其实是使用了 runInteraction 这个接口函数的。具体不同的事务,adbapi是将相应的callback作为其第一个参数,然后在 deferToThreadPool 时指定线程运行该callback来实现。所以,我们只需要为MySQL定义一种新的事务就可以了。

  下面就是我们需要定义的新事务:


  1. def runMySQLInsert(self, *args, **kw):
  2.     assert self.dbapiName == 'MySQLdb'
  3.     return self.runInteraction(self._runMySQLInsert, *args, **kw)

  4. def _runMySQLInsert(self, trans, *args, **kw):
  5.     trans.execute(*args, **kw)
  6.     return nnection.insert_id()

Ok,接下来,把这两个函数Monkey Patch到adbapi上就完事了:)

阅读(1144) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~