Существует ли Java API отслеживания/управления версиями изменений объектов?

Я знаю, по крайней мере, два усилителя байтового кода, которые изменяют "объектную модель" во время выполнения, чтобы транзакция выполнялась прозрачно. Один из них является частью Versant VOD, который я использую на работе каждый день, а другой-частью терракоты. Вероятно, есть и другие, например, в Орме, но Версант заботится об этом в моей компании.

мой вопрос в том, есть ли такой API с открытым исходным кодом, который можно использовать самостоятельно, независимо от продукта, который он был предназначен для? Вы можете сказать "взломанный" API. Он должен только отслеживать изменения, не доступ для чтения, что значительно замедлит код. Другими словами, он не должен требовать явной блокировки чтения/записи. Это требует либо доступа ко всем классам, которые выполняют изменения, а не только к модели данных, либо для сравнения требуется сохранить в памяти некоторую форму "предыдущей версии".

проблема, которую я пытаюсь решить, заключается в том, что у меня есть" большой " (32K до 256K) объект графики, которые "сериализованы" в БД (NoSQL). Они долговечны и должны быть регулярно повторно сериализованы, чтобы иметь "историю" изменений. Но они довольно дороги для сериализации, и большинство изменений незначительны.

Я мог бы сериализовать их полностью каждый раз и запустить двоичный diff в потоке, но это звучит очень интенсивно. Лучшим решением был бы API, который изменяет операции записи на модели для протоколирования изменений, так что после сохранения исходного "образа" только протокол необходимо сохранить.

Я нашел некоторые вопросы, говорящие об Apache Commons Beanutils для сравнения объектов, но это не полезно для изменений на месте; мне нужно было бы сделать полный клон модели между каждой "бизнес-транзакцией".

чтобы повторить, я ищу API "в памяти", в том же JVM, который не включает какое-либо внешнее серверное приложение. API с собственным кодом в порядке, если они доступны на Win, Mac и Linux. API делает не должны быть в настоящее время упакованный независимо; просто должно быть возможно извлечь его из" родительского проекта", чтобы сформировать независимый API (лицензия родительского проекта должна позволить это).

мои объектные графики будут включать в себя много больших массивов, и поэтому их необходимо эффективно поддерживать.

изменения необходимы не только для аудита, но и для того, чтобы их можно было воспроизвести или отменить. Точнее, с десериализованным начальным графом и списком изменения, я должен прийти к идентичному конечному графику. Кроме того, начиная с конечного графика, можно вернуться к исходному графику, применив изменения в обратном порядке. Это использует точно такую же функциональность, но требует, чтобы протокол изменения сохранял старое значение в дополнение к новому значению.

лицензия API должна быть совместима с коммерческим использованием.

[EDIT] до сих пор я не получил полезное ответ, и это не похоже на то, что я хочу существует. У меня остается только один выход: сделать так, чтобы это произошло. Я опубликую ссылку здесь как ответ, когда у меня будет рабочая реализация, так как это следующий шаг в моем проекте, и я не могу идти вперед без него.

[EDIT] я случайно нашел этот несколько связанный вопрос:есть ли библиотека Java, которая может "различать" два объекта?

4 ответов


Kryo v1 имел сериализатор, который знает о последних данных, которые были сериализованы и только испускает дельту. При чтении он знает о последних полученных данных и применяет дельту. Дельта выполняется на уровне байтов. здесь - это сериализатор. Большая часть работы выполняется этот класс. Это может быть использовано несколькими полезными способами, например, сетью, подобной Quake 3.

Это было опущено в Kryo v2, потому что AFAIK его никогда не использовали. Кроме того, это не имеют обширного набора тестов. Он может быть портирован, хотя и может делать то, что вам нужно, или служить основой для того, что вам нужно.

выше также опубликовано на JVM сериализаторы рассылки.

делать это на уровне объекта было бы немного сложно. Вы можете написать что-то похожее на FieldSerializer который одновременно ходит по двум объектным графам, это будет автономный код, а не сериализатор Kryo. На каждом уровне вы можете назвать равными. Напишите байт, чтобы при чтении вы знали, равен ли он. Если не равно, используйте Kryo для записи объекта. Equals будет вызываться много раз для одного и того же объекта, особенно для глубоко вложенных объектов.

другой способ, которым вы могли бы это сделать, - это сделать только выше для скаляров и строк, т. е. только значения, написанные выходным классом. Проблема доступности две графы объектов. Чтобы использовать Kryo, я думаю, вам нужно будет дублировать все сериализаторы, чтобы узнать о другом объекте диаграмма.

возможно, вы могли бы использовать Kryo с вашим собственным выходом, который собирает значения в списке вместо их записи. Используйте это для "сериализации" вашего старого графа объектов. Теперь напишите другую версию вашего собственного вывода, которая принимает этот список и использует его для сериализации нового графа объектов. Каждый раз, когда записывается значение, сначала проверьте его со следующим объектом в списке. Если равно, напишите 1. Если не равно, напишите 0, а затем значение.

Это может быть сделано более экономичные по используя первый вывод дважды, один раз на старом и один раз на новом графике. Теперь у вас есть два списка значений. Используйте их для записи битовой строки, обозначающей, которые равны. Это экономит место при записи целого байта для каждого значения, но имеет накладные расходы дополнительного списка. Наконец, запишите все значения, которые не равны.

чтобы закончить эту идею, вам нужно иметь возможность десериализовать данные. Вам понадобится собственная версия входного класса, который принимает список значений из старого объекта диаграмма. Ваш ввод сначала считывает битовую строку (или байт на значение). Для значения, которое было равно, он возвращает значение из списка вместо чтения из данных. Если значение не было равно, он вызывает метод super для чтения из данных.

Я не уверен, если это будет быстрее, чем делать это на уровне байтов. Если бы мне нужно было угадать, я бы сказал, что это, вероятно, будет быстрее. Хранение всех значений в списке будет много бокса / распаковки, и этот подход по-прежнему назначает все поля, даже если они не изменился. Я сомневаюсь, что производительность будет проблемой в любом случае, поэтому я, вероятно, просто выберу более простой подход. Трудно сказать, что это такое... воскресите Дельта-материал или напишите свои собственные классы вывода/ввода.

Если вы хотите внести свой вклад обратно в крио, это, конечно, было бы здорово. :)


посмотри API репозитория контента для Java, используется Artifactory для управления зависимостями maven. The Apache Зайца является ссылочной реализацией этого JSR (JSR-283 версия 2)


Я не знаю такого API, но это не может быть так сложно:

лучшим решением был бы API, который изменяет операции записи на модели для протоколирования изменений, так что после сохранения исходного "образа" необходимо сохранить только протокол.

Я бы сказал, что вам нужны только 2 компонента: Action и ActionProcessor

вам нужно только сохранить список (протокол) выполненных действий.

interface ActionProcessor{
    void perform(Action action);
    void undoToDate(Date date);
} 

iterface Action{
    Date getDate();
    void perform();
    void undo();
}      

насколько я знаю, GemFire-это корпоративный продукт Gemstone (теперь VmWare), который делает что-то похожее на Gemstone smalltalk OODB, но затем для java. Джеймс Фостер создал