ZODB无法提交

Gag*_*gan 2 python zodb

我是第一次使用ZODB.只是尝试使用FileStorage提交数据.但是当我第二次执行相同的脚本时,我无法提交新对象.这是我的剧本

from ZODB import FileStorage,DB
import transaction    
storage = FileStorage.FileStorage('/tmp/test.fs')
db = DB(storage)
conn = db.open()
root = conn.root()
#root['layer']={}
root['layer']['2b']={"id":'2b','name':'some name'}
transaction.commit()
conn.close()
db.close()
storage.close()
Run Code Online (Sandbox Code Playgroud)

当我再次重复代码时,只需更改id root['layer']['2c']并从python中退出,第二次对象就不会被提交.我只有第一个对象.可能是什么原因.

Mar*_*ers 5

ZODB持久层通过挂钩到python __setattr__钩子来检测更改,每次设置属性时都将持久对象标记为已更改.

但是如果你使用像python字典这样的原始可变对象,那么持久性机制就无法检测到这些变化,因为没有写入任何属性.您有三种方法可以解决此问题:

使用持久映射

持久化包包括一个持久映射类,它基本上是一个持久的python字典实现,并通过挂钩__setitem__和其他映射挂钩直接检测更改.root示例中的对象基本上是持久映射.

要使用,只需用持久映射替换所有字典:

from persistent.mapping import PersistentMapping
root['layer'] = PersistentMapping()
Run Code Online (Sandbox Code Playgroud)

通过触发挂钩强制进行更改检测

您可以再次设置密钥,或者在持久对象上再次设置属性以强制更改对象:

root['layer'] = root['layer']
Run Code Online (Sandbox Code Playgroud)

将持久对象标记为已更改

您可以_p_changed在最近的持久对象上设置标志.您的根对象是您拥有的唯一持久对象,其他所有内容都是python词典,因此您需要将其标记为已更改:

root._p_changed = 1
Run Code Online (Sandbox Code Playgroud)