ZODB 讨论中

::-- hoxide [DateTime(2005-02-20T06:24:40Z)] TableOfContents

ZODB

简述

起因

学习笔记

ZODB的安装

基本概念

例子

   1 from ZODB import FileStorage, DB
   2 import ZODB
   3 from Persistence import Persistent
   4 from BTrees.OOBTree import OOBTree
   5 
   6 class User(Persistent):
   7     pass
   8 
   9 def test1():
  10     storage = FileStorage.FileStorage("test-filestorage.fs")
  11     db = DB(storage)
  12     conn = db.open()
  13     dbroot = conn.root()
  14     # Ensure that a 'userdb' key is present
  15     # in the root
  16     if not dbroot.has_key('userdb'):
  17         dbroot['userdb'] = OOBTree()
  18     userdb = dbroot['userdb']
  19     # Create new User instance
  20     newuser = User()
  21     # Add whatever attributes you want to track
  22     newuser.id = 'amk'
  23     newuser.first_name = 'Andrew'
  24     newuser.last_name = 'Kuchling'
  25     # Add object to the BTree, keyed on the ID
  26     userdb[newuser.id] = newuser
  27     # Commit the change
  28     get_transaction().commit()
  29     conn.close()
  30     storage.close()
  31 
  32 def test2():
  33     storage = FileStorage.FileStorage("test-filestorage.fs")
  34     db = DB(storage)
  35     conn = db.open()
  36     dbroot = conn.root()
  37     it = [dbroot]
  38     for t in it:
  39         for k, v in t.items():
  40             if isinstance(v, OOBTree):
  41                 print k, ':'
  42                 it.append(v)
  43             elif isinstance(v, User):
  44                 print 'Key:', k
  45                 print 'ID:', v.id
  46                 print 'first_name:', v.first_name
  47                 print 'last_name:', v.last_name
  48     
  49 if __name__ == "__main__":
  50     test1()
  51     test2()

逐步分解

   1 from ZODB import FileStorage, DB
   2 storage = FileStorage.FileStorage('/tmp/test-filestorage.fs')
   3 db = DB(storage)
   4 conn = db.open()

   1 import ZODB
   2 from Persistence import Persistent
   3 
   4 class User(Persistent):
   5     pass

   1 dbroot = conn.root()
   2 # Ensure that a 'userdb' key is present
   3 # in the root
   4 if not dbroot.has_key('userdb'):
   5    from BTrees.OOBTree import OOBTree
   6    dbroot['userdb'] = OOBTree()
   7 userdb = dbroot['userdb']

dbroot和userdb都是OOBTree的实例, 什么是BTree稍后解释, 你可以暂且认为是ZODB化的dict.

做userdb中插入一条User记录:

   1 # Create new User instance
   2 newuser = User()
   3 # Add whatever attributes you want to track
   4 newuser.id = 'amk'
   5 newuser.first_name = 'Andrew' ; newuser.last_name = 'Kuchling'
   6 ...
   7 # Add object to the BTree, keyed on the ID
   8 userdb[newuser.id] = newuser
   9 # Commit the change
  10 get_transaction().commit()

你也许会奇怪get_transaction()是哪来的, 有什么用? get_transaction是在import ZODB的时候加入到builtins里面的, 他获得一个事务.

   1 conn.close()
   2 storage.close()

   1     storage = FileStorage.FileStorage("test-filestorage.fs")
   2     db = DB(storage)
   3     conn = db.open()

然后获取dbroot:

   1 dbroot = conn.root()

   1     it = [dbroot]
   2     for t in it:
   3         print t
   4         for k, v in t.items():
   5             if isinstance(v, OOBTree):
   6                 print k, ':'
   7                 it.append(v)
   8             elif isinstance(v, User):
   9                 print 'Key:', k
  10                 print 'ID:', v.id
  11                 print 'first_name:', v.first_name
  12                 print 'last_name:', v.last_name

这个只是试验,证明test1的确在数据库中存放了数据.

至此例子分析完毕.

ZODB的关系模型

顾名思义他们分别是用来模拟Mapping结构和List结构的(python中的dict和list).

为什么要提供这两种结构呢?因为ZODB不能有效得处理python中的可变对象(dict和list). 当改变ZODB对象时, 应该将对象标记为脏的(dirty),这样在commit时就知道到底哪些数据需要更新了. 在ZODB对象中用'_p_changed'属性标记脏数据.

但是在改变可变类型时_p_changed并不改变, 需要用户手动设置, 如:

   1 userobj.friends.append(otherUser)
   2 userobj._p_changed = 1

PersistentMapping, PersistentList只解决了正确性的问题. 而BTree则应该是真正ZODB化的解决方案.

BTree