2008-01-11

ZODB and Persistent Objects.txt

  2008-01-11 19:02

Что такое ZODB и PersistentObjects : ZODB позволяет активировать объект (восстанавливать его состояние в оперативной памяти) и сохранять объект в хранилище. Класс _не_сохраняется_ в ZODB ни при каких обстоятельствах, так же как и атрибуты класса. ...

Что такое ZODB и PersistentObjects :

ZODB позволяет активировать объект (восстанавливать его состояние в оперативной памяти) и сохранять объект в хранилище. При этом нужно понимать где проходит граница объекта: иначе объем транзакций окажется недопустимо большим.

Чтобы объект сохранялся в ZODB, он должен быть унаследован от persistent.Persistent.

Обратите внимание, что на самом деле, объект - это не один объект. Объект - это объект и значения его атрибутов, которые, вообще говоря, тоже объекты. При сериализации объекта он "вырезается" из сети ссылающихся друг на друга объектов по границе ссылки на объект, порожденный от persistent.Persistent: при этом сам объект заменяется ссылкой на него.

Кроме того, осознайте разницу между классом и объектом (и, соответственно, атрибутами класса и объекта). Класс _не_сохраняется_ в ZODB ни при каких обстоятельствах, так же как и атрибуты класса. Поэтому если класс имеет мутируемые атрибуты, они должны быть явно переприсвоены при инстанциировании объекта этого класса. Обычно это делается в функции __init__, впрочем, стандартные формы редактирования класса также выполняют переприсваивание.

Рассмотрим пример:

        class A(persistent.Persistent) :

            def __init__(self) :
                self.b = [1, [ 3, None] ]

            a = None

            b1 = [1, [ 3, None] ]

            c = 1

            d = None

        class C(persistent.Persistent) : pass

        class D(object) : pass

        a = A()

        a.a = A()

        a.b[1][1] = C()

        a.b1[1][1] = C()

        d = D()

        d.c = C()

        a.d = d

При сохранении объекта "a" в одной записи базы данных будут сохранены:

  • атрибут a.a как ссылка;
  • a.b - сохраняется полностью (как значение), но элемент a.b[1][1] заменяется ссылкой;
  • a.b1 - не сохраняеется вообще, так как это атрибут класса. Новое значение будет существовать до перезагрузки сервера.
  • a.c - сохраняется значение;
  • a.d - сохраняется как значение;
  • a.d.c - заменяется ссылкой.

Соответственно, активация объекта восстановит его в памяти таким же образом - т.е. восстановит ссылки на объекты вместо самих объектов - однако попытка обращения по атрибуту, значение которого заменено ссылкой, приведет к активации очередного объекта и в ответ на запрос атрибута будет получено значение, а не ссылка.

Процедура сохранения-восстановления прозрачна: программисту практически не приходится беспокоится о сохранении состояния, все происходит автоматически до тех пор, пока изменяется объект, порожденный от persistent.Persistent. Однако, если значением атрибута является мутирующий объект, не порожденный от persistent.Persistent, его изменение может пройти незаметно для ZODB:

        class A(persistent.Persistent) : 

            a = 1

            b = [0,1,2]

        a = A()

        # следующие изменения будут сохранены автоматически

        a.a = 2

        a.b = [0,1,3]

        # следующие изменения пройдут незамеченными

        a.b.append(10)

        a.b[0]=2

Чтобы сохранить объект, мутирующие атрибуты которого изменились, нужно явно указать, что состояние объекта изменилось:

        a._p_changed = True

Или же просто использовать соответствующую технику программирования:

        # вместо a.b.append(10)

        # пишем a.b = a.b + [10]

        # вместо a.b[0] = 2

        # пишем a.b = [2] + a.b[1:]

Второй способ методологически более предпочтителен, но ресурсоемок, т.к. приводит к лишнему копированию объекта в памяти. Какой способ использовать - зависит от программиста, но важно просто представлять себе как это работает. По поводу использования (и неправильного использования) persistent-переменных рекомендуется прочитать статью somepersistentwarning.txt.

Официальный сайт Zope3 Московская группа изучения реактивного движения The Dream Bot Site noooxml