3.4Python之对象数据库ZODB

Python 专栏收录该内容
33 篇文章 0 订阅
一、基本概念
关系数据库并不是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”文件


ZODB官方: http://www.zodb.org

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值