sqlalchemy 的文档可谓典范,谁叫作者还开发着模板语言(myghty、mako)呢,呵呵。其实 sqlalchemy 的文档就是用 myghty 写的。
不过系统复杂了,功能多了,再好的文档也会让人迷路。最近用了用 sqlalchemy ,对这一点感受颇深,故把临时想到的几个比较常用的功能摘录如下,提纲挈领,既为自己整理一下思路,也让新手一窥 sqlalchemy 的精华。
- Eager Loading Join,本是关系数据库中多么常见的操作,怎奈 django 的 orm 就是不支持,SQLObject 的做法也很不如人意。
- Association Object many-to-many 关系都是通过增加一个中间表来实现,映射到对象后,这个中间表就不需要我们再操心了,会隐式地进行处理。 不过对于多个实体两两之间多对多关系,往往另外再增加一个关联对象会更方便。 这样的例子其实也不少,比如:user-bookmark-tags、产品-元件-元件供应商(这是一次期末考试题目里面的 ;-)
- Deferred Column Loading 比如文章表里面的 body 字段通常比较大,在获取文章列表时这个字段就不必取出来了。甚至如果你有某个字段存的是文件的话,这个功能就更加重要了。 这本是个不起眼的小功能,不过上次看到 javaeye 中有一贴说到大名鼎鼎的 Hibernate 都对这个功能实现得这么痛苦后,我蓦然发现 sa 真的很 nb。呵呵,托了动态语言的福了吧。
- Mapping a Class with Table Inheritance 如何把对象间继承关系映射到关系数据库,sqlalchemy 提供三种方式: single table inheritance 所有子类型都放在一个表中; concrete table inheritance 每一种子类型存在独立的表中; multiple table inheritance 父子类型都存在独立的表中,查询的时候进行连接; 显然最后一种是冗余最少的,不过查询的时候要做一次连接操作,如何选择还是看具体情况了。
- Mapping a Class against Arbitary Selects 将对象映射到任意的 select,其实也就是任意的 sql 子查询。 这功能太强大了,有了这个后,我们就可以骄傲地宣称,(几乎)没有什么是 sqlalchemy 做不了的了!
- Identity Map session 在 sqlalchemy 中是一个非常重要的概念,session 跟踪对象的修改情况,跟踪对象之间的关联,智能判断数据库操作执行的顺序等等。 Identity Map 是 session 中一个容易让人掉入陷阱的概念,你可以把它想象成一个以数据表主键为key的cache。每次从数据库查询后,如果 sqlalchemy 发现 Identity Map 中已经有了相同主键的实例,那就不会重新生成实例了。因为如果存在多个实例会带来许多问题,比如多个实例分别修改并保存时就会产生混乱。 偶尔 Identity Map 也会产生一些意想不到的行为,比如 ticket 458 ,不过理解了 Identity Map 的机理后,也就没什么问题了。 值得一提的是,Mapper Options 有一个 always_refresh 参数,如果把它设为True,则对该 mapper 的任何查询操作都会自动使用从数据库中查询到的数据覆盖 Identity Map 中已有的实例,这样要是对旧实例做过什么还没保存的修改的话,就都没了。所以要慎用!
- Cascade rules 最后这个也是很有用的功能,举个例子来说吧,user 和 article 有一对多的关系,现在删除一个 user,是否应该把相关的 article 也删了呢,要 article 还有其他的依赖关系呢?这些决定当然是要根据实际的需求来,而控制这些行为的方法就是通过 relation 的 cascade 参数,具体取值及其含义看文档去吧。
总滴来说,本文只是个提纲的作用,具体还得去看文档,看示例,看unittest。
最后还想说两句的就是,大家之所以选择 ORM ,主要原因是逃离 SQL,然而我感觉不能掌握 SQL 是不能(很好)掌握sqlalchemy的。至少要对关系数据库的这些概念了解,理解 SQL 就是理解关系数据库。只有这样才能利用sqlalchemy将关系数据库发挥到极致!
使用 sqlalchemy 的好处就是不用写 sql 了,屏蔽不同dbms之间SQL语法的区别,同时又让你在需要的时候能够利用到不同 DBMS 提供的一些独特特性,让你以对象的方式管理数据库访问代码,提高代码重用性!
4 评论:
你对ORM的了解可能还不够......
1. Eager Loading
Django 是 Active Record 模式,不是 Data Mapper,所以不具有这个功能。
3. Deffered Column Loading
Hibernate 3.0 就已经支持到 Column 级别的 Lazy Loading了,不是 SA 牛B,这种功能没必要吹嘘的这么厉害。
4. Mapping a Class with Table Inheritance
如果这点都做不到,那就不要说自己的 ORM 了。
..... 之后几点反正都是学 Hibernate 嘛,没什么大不了的。
hibernate 功能的完善确实有过耳闻,不过我这篇文章的主要比较对象还是在 python 社区里面。说得具体点就是 django orm 和 sqlobject 两个了。当然也许确实如你所说,设计思想不同,不太具备可比性。不过我常常感觉 Active Record 这种思路是引人走向歧途,现实世界的系统不可能不用到关系数据库的一些“高级”概念,而那个时候,就不得不退回到 sql 了。
"""
3. Deffered Column Loading
Hibernate 3.0 就已经支持到 Column 级别的 Lazy Loading了,不是 SA 牛B,这种功能没必要吹嘘的这么厉害。
"""
我也没说 hibernate 没有实现,只不过看到那帖子里面说很麻烦,重新编译PO什么的。
"""
4. Mapping a Class with Table Inheritance
如果这点都做不到,那就不要说自己的 ORM 了。
"""
不过Active Record风格的orm还是做不到这么细致的控制的。
而要拿 sqlalchemy 和 hibernate 比的话,优势也是很大的,pythonic,呵呵。当然sa成熟度肯定还是不够的,还需要发展。
不错 技术含量太高了
都是高人啊
发表评论