一. 概述
ZODB是一个可拓展和冗余的数据库,专注于存储可拓展的对象。
使用ZODB的好处:
- 使对象持久化对代码几乎没有影响,代码和数据库之间几乎没有接缝。
- 没有部分隐藏数据库的数据库映射程序。
- 象之间的关系处理得非常自然,支持没有连接的复杂对象图。
- 数据本地保存,不需要安装软件和搭建环境。
官方文档:http://www.zodb.org/en/latest/
安装:pip install ZODB
二. 基本使用
1. 存储数据
# -*-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()
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()
2. 获取数据
# -*-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()
db = MyZODB('./Data.fs')
dbroot = db.dbroot
for key in dbroot.keys():
print(key + ':', dbroot[key])
db.close()
3. 更改数据
# -*-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()
db = MyZODB('./Data.fs')
dbroot = db.dbroot
# dbroot['a_string'] = 'Gift啊'
# transaction.commit()
# db.close()
# 更改字典数据时
a_dict = dbroot['a_dictionary']
a_dict[1920] = '1234567'
# 设置数据库的根属性,通知他需要重新存储其下的属性
dbroot._p_changed = 1
transaction.commit()
db.close()
4. 删除数据
# -*-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()
db = MyZODB('./Data.fs')
dbroot = db.dbroot
del dbroot['a_number']
transaction.commit()
db.close()
三. 综合案例:模拟银行存取款系统
# -*-coding: UTF-8 -*-
import ZODB
import ZODB.FileStorage as ZFS
import transaction
import persistent
class OutOfFunds(Exception):
pass
class Account(persistent.Persistent):
def __init__(self, name, start_balance=0):
self.name = name
self.balance = start_balance
def __str__(self):
return f"Account: {self.name}, balance: {self.balance}"
def __repr__(self):
return f"Account: {self.name}, balance: {self.balance}"
def deposit(self, amount):
"""save amount into balance"""
self.balance += amount
def withdraw(self, amount):
"""withdraw from balance"""
if amount > self.balance:
raise OutOfFunds
self.balance -= amount
return self.balance
class ZODBUtils:
conn = None
filestorage = None
def openConnection(self,file_name):
self.filestorage = ZFS.FileStorage(file_name)
db = ZODB.DB(self.filestorage)
self.conn = db.open()
return self.conn
def closeConnection(self):
self.conn.close()
self.filestorage.close()
def init_balance():
zodbutils = ZODBUtils()
conn = zodbutils.openConnection('zodb_filestorage.db')
root = conn.root()
noah = Account('noah', 1000)
print(noah)
root['noah'] = noah
jermy = Account('jermy', 2000)
print(jermy)
root['jermy'] = jermy
transaction.commit()
zodbutils.closeConnection()
def app():
zodbutils = ZODBUtils()
conn = zodbutils.openConnection('zodb_filestorage.db')
root = conn.root()
noah = root['noah']
print("Before Deposit Or Withdraw")
print("=" * 30)
print(noah)
jermy = root['jermy']
print(jermy)
print('-' * 30)
transaction.begin()
noah.deposit(300)
jermy.withdraw(300)
transaction.commit()
print("After Deposit Or Withdraw")
print("=" * 30)
print(noah)
print(jermy)
print("-" * 30)
zodbutils.closeConnection()
if __name__ == '__main__':
init_balance()
app()