3.4Python之对象数据库ZODB
一、基本概念
关系数据库并不是Python程序员可用的解决方案。通常,对象数据库可能更适合解决某些问题。ZODB是一个可扩展和冗余的对象数据库,其专注于存储可扩展的对象,而没有天生“对象-关系”不匹配情况:在尝试将面向对象的语言与关系查询系统映射对象建立关系时,可能会出现这种不匹配情况。
二、ZODB使用
建立和断开与ZODB的连接
连接到ZODB的标准方法设计创建四个对象:存储数据库数据的方法、围绕存储并未存储提供实际数据库行为“db”包装、启动与该数据库的特定会话“connection”对象、允许我们访问包含在数据库中的对象层次结构的根的“dbroot”对象。以下所有代码示例都需要将下面代码片段放在Python文件中的示例代码前面,以便正确地打开和关闭ZODB示例:
使用ZODB
#-*-coding: UTF-8 -*-
from ZODB import FileStorage, DB
import transaction
class MyZODB(object):
def __init__(self, path):
self.storage = FileStorage.FileStorage(path)
self.db = DB(self.storage)
self.connection = self.db.open()
self.dbroot = self.connection.root()
def close(self):
self.connection.close()
self.db.close()
self.storage.close()
存储简单Python数据
ZODB数据库可以存储所有类型的Python对象。
存储简单Python数据
from myzodb import MyZODB, transaction
db = MyZODB('./Data.fs')
dbroot = db.dbroot
dbroot['a_number'] = 3
dbroot['a_string'] = 'Gift'
dbroot['a_list'] = [1, 2, 3, 5, 7, 12]
dbroot['a_dictionary'] = { 1918: 'Red Sox', 1919: 'Reds' }
dbroot['deeply_nested'] = {
1918: [ ('Red Sox', 4), ('Cubs', 2) ],
1919: [ ('Reds', 5), ('White Sox', 3) ],
}
transaction.commit()
db.close()
获取简单数据
from myzodb import MyZODB
db = MyZODB('./Data.fs')
dbroot = db.dbroot
for key in dbroot.keys():
print key + ':', dbroot[key]
db.close()
运行结果:
注意:我们使用文件名"Data.fs"纯粹是为了遵循传统,因为许多ZODB安装在使用特定文件名方面实际上已经实现了标准化,你可以随心所欲地使用任何名称。
更改简单数据
当将某个键设置为新值,ZODB始终能够了解这一点。因此,对上面的数据库进行类型如下的更改将会自动别检测和持久化:
db = MyZODB('./Data.fs')
dbroot = db.dbroot
dbroot['a_string'] = 'Something Else'
transaction.commit()
db.close()
但是,需要显示地将对列表或字典的更改告诉ZODB,因为ZODB无法了解所做的更改。这是持久性框架中的一个规定的可变性和参与功能。下面的代码不会导致ZODB看到更改:
a_dictionary = dbroot['a_dictionary']
a_dictionary[1920] = 'Indians'
transaction.commit()
db.close()
如果打算更改——而不是完全替换——类似如此的复杂对象,需要设置数据库根的属性 _p_changed,以通知它需要重新存储其下的属性:
a_dictionary = dbroot['a_dictionary']
a_dictionary[1920] = 'Indians'
db._p_changed = 1
transaction.commit()
db.close()
删除对象:
del dbroot['a_number']
transaction.commit()
db.close()
注意:如果没有调用transaction.commit(),则上面更改都不会对数据库产生任何影响。正如在关系数据库中一样,只有通过提交已执行的操作,这些操作才会出现在数据库里。
持久化对象
当然,很少有Python程序员希望使用上面的诸如列表、元祖和字典等日益复杂的数据结构。相反,希望创建全能的Python对象,并且其属性将会自动地持久化。下面介绍如何定义一个可持久到数据库的类型。为此,该类将必须从Persistent继承。
from persistent import Persistent
class Host(Persistent):
def __init__(self, hostname, ip, interfaces):
self.hostname = hostname
self.ip = ip
self.interfaces = interfaces
存储对象
现在可以创建该类的几个实例,并在ZODB中将其持久化:
from mymodel import Host
host1 = Host('www.example.com', '192.168.7.2', ['eth0', 'eth1'])
dbroot['www.example.com'] = host1
host2 = Host('dns.example.com', '192.168.7.4', ['eth0', 'gige0'])
dbroot['dns.example.com'] = host2
transaction.commit()
db.close()
获取对象
from mymodel import Host
for key in dbroot.keys():
obj = dbroot[key]
if isinstance(obj, Host):
print "Host:", obj.hostname
print " IP address:", obj.ip, " Interfaces:", obj.interfaces
db.close()
更改对象
正如“dhroot”对象能够自动检测在其键索引处放置的值一样,持久化对象将在您设置其属性时,自动执行检测,并将属性保存到数据库。
host = dbroot['www.example.com']
host.ip = '192.168.7.141'
transaction.commit()
db.close()
但是,如果您在某个对象下面存储复杂数据类型,则会出现与连接到数据根的复杂数据类型完全相同的问题。必须像前面一样设置
_p_changed 属性:
host = dbroot['www.example.com']
host.interfaces.append('eth2')
host._p_changed = 1
transaction.commit()
db.close()
后,ZODB数据库实例很容易维护。由于ZODB数据库实例不包含需要设计或修改的模式,要执行的例行维护是定期压缩以防止其耗尽整个磁盘。为了支持事务回滚,写到ZODB数据库的每个新的更改实际上都是追加到“Data.fs”文件,而不是更新该文件中已经存在的信息。要删除随着事务提交二积累的旧信息,ZODB管理员必须偶尔对其数据进行压缩。
注意:一次只有一个程序能够安全地打开“Data.fs”文件
参考地址:
http://www.ibm.com/developerworks/cn/aix/library/au-zodb/
ZODB官方:
http://www.zodb.org
————————————————
版权声明:本文为CSDN博主「阿兵-AI医疗」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/webzhuce/article/details/52662298
相关文章