用动态语言编写一些简单的应用时,好的 ORM 往往能带来开发效率的提升 —— 尽管 ORM 为不少大型项目所不齿。Python 社区的 ORM 框架最著名的莫属 SQLAlchemy,它的特点是利用 Python 的元编程支持构造了一套既能照顾到面向对象开发习惯,又能向下支持复杂数据库查询操作的 DSL。这类框架在分类上,应该属于抽象层。
抽象层的一个问题,就是在应用本身的业务复杂度之外又增加了额外的“抽象复杂度”,加上去的复杂度是要花费开发者额外精力去理解的。我在使用 SQLAlchemy 的过程中,也因为对这层附加上去的复杂度理解不深,掉了许多次坑。掉坑的次数多了,我慢慢有点感觉有些“危险的路径”坑是比较多的,有些安全的路径是比较太平的。这种感觉还不成体系,暂时先写这么一篇博客记录下来,希望日后的开发学习中再求理解。
SQLAlchemy 的使用方式
SQLAlchemy 曾经的使用方式比较繁琐,需要自己定义 Engine (数据访问层)、 Metadata (数据库 Schema 定义)、 Table (表结构定义)、 Mapper (映射规则),然后用 Mapper 将 Metadata 映射到目标模型类中。需要使用模型类的时候,建立 Session (数据库访问会话)并用业务方法修改模型数据,然后提交会话,SQLAlchemy 的控制流一层层往回走,数据的前后变动被 Session 内部的[工作单元][0]析出,经过 Metadata 整理成查询 DSL,再由 Engine 转换成本地数据库驱动支持的 SQL 方言。
后来大概是被反复吐槽这样太麻烦了吧,SQLAlchemy 开发组就在新版本中支持了一种稍微简洁一些的用法,即用定义类的方式定义表的结构。通过描述符、元类等元编程手段,SQLAlchemy 自动生成上述构建。有了这一机制,SQLAlchemy 用起来就和 Django Model 很像了,如下。