Обработка обслуживания данных в Объектных базах данных как db4o

Одна вещь, которую я постоянно находил очень сбивающими с толку об использовании объектной базы данных как db4o, состоит в том, как Вы, как предполагается, обрабатываете сложные миграции, которые обычно обрабатывались бы SQL/PL-SQL.

Например, предположите, что у Вас была таблица в реляционной базе данных, названной my_users. Первоначально у Вас был столбец, названный "full_name", теперь, когда Ваше программное обеспечение находится в V2, Вы хотите удалить этот столбец, разделить полные имена на пробеле и поместить первую часть в столбец, названный "first_name" и вторым в столбце, названном last_name. В SQL я просто заполнил бы "first_name", и "second_name" столбцы затем удаляют первоначальный столбец, названный "full_name".

Как я сделал бы это в чем-то как db4o? Я пишу программу Java что сценарии, ищущие все объекты User.class, устанавливая в NULL full_name при установке first_name и last_name? Когда я делаю свою следующую фиксацию svn, там не будет никакое поле/свойство компонента, соответствующее full_name, это было бы проблемой? Кажется, как будто использовать его в производственном приложении, где моя "схема" изменяется, я хотел бы записать, что сценарий для миграции данных от версии x до версии x+1 и затем в версии x+2 на самом деле удаляет свойства, от которых я пытаюсь избавиться для версии x+1, поскольку я не могу записать сценарий Java для изменения свойств, которые больше не являются частью моего типа.

Кажется, что часть проблемы - то, что RDBMS разрешает то, что возражает, что Вы обращаетесь к на основе простого нечувствительного к регистру основанного на операция со строками имени на языке как Java, ввод более сложен, чем это, Вы не можете обратиться к свойству, если метод считывания/метод set/поле не является членом класса, загруженного во времени выполнения, таким образом, у Вас по существу должно быть 2 версии Вашего кода в том же сценарии (хм, пользовательские classloaders походят на боль), имейте новую версию своего сохраненного класса, принадлежат другому пакету (звучит грязным), или используйте стратегию версии x+1 x+2, которую я упомянул (требует намного большего количества планирования). Возможно, существует некоторое очевидное решение, которое я никогда не подбирал из db4o документов.

Какие-либо идеи? Надо надеяться, это имеет некоторый смысл.

8
задан benstpierre 10 March 2010 в 21:21
поделиться

2 ответа

Во-первых, db4o обрабатывает «простые» сценарии, такие как автоматическое добавление или удаление поля . Когда вы добавляете поле, все существующие объекты сохраняют значение по умолчанию. Когда вы удаляете поле, данные существующего объекта все еще находятся в базе данных, и вы все еще можете получить к нему доступ. Поле переименования и т. Д. Представляют собой специальные вызовы «рефакторинга» .

Теперь в вашем сценарии вы бы сделали что-то вроде этого:

  1. Удалите поле «full_name», добавьте новые поля «first_name» и «second_name»
  2. Переберите все объекты «Address»
  3. Получите доступ к старое поле с помощью API-интерфейса StoredClass
  4. . Разделить, изменить, обновить и т. д. значение. Установите новые значения в новом поле и сохраните объект.

Предположим, у нас есть класс Address. Поле full_name было удалено. Теперь мы не хотим копировать его в «имя» и «фамилию». Тогда это могло бы выглядеть так (Java):

    ObjectSet<Address> addresses = db.query(Address.class);
    StoredField metaInfoOfField = db.ext().storedClass(Address.class).storedField("full_name", String.class);
    for (Address address : addresses) {
        String fullName = (String)metaInfoOfField.get(address);
        String[] splitName = fullName.split(" ");
        address.setFirstname(splitName[0]);
        address.setSurname(splitName[1]);
        db.store(address);
    }

Как вы предложили, вы должны написать код миграции для каждого повышения версии. Если поле больше не является частью вашего класса, вы должны получить к нему доступ с помощью API-интерфейса StoredField, как указано выше.

Вы можете получить список всех «сохраненных» классов с помощью ObjectContainer.ext (). StoredClasses () . С помощью StoredClass.getStoredFields () вы можете получить список всех полей магазина, нет, это поле больше не существует в вашем классе. Если класс больше не существует, вы все равно можете получить объекты и получить к нему доступ через класс GenericObject.

Обновление: для более сложных сценариев, когда базу данных необходимо переносить с помощью нескольких шагов версии.

Например, в версии v3 адрес-объект выглядит совершенно иначе.Таким образом, «сценарий миграции» для версии v1 в v2 больше не имеет требуемых полей (имя и имя в моем примере). Я думаю, что есть несколько возможностей справиться с этим.

  1. (Предполагая Java для этой идеи. Конечно, есть эквивалент в .NET). Вы можете сделать шаг миграции Groovy-скриптом . Так что каждый сценарий не мешает другому. Затем вы определяете «классы», необходимые классы для миграции. Таким образом, каждая миграция имеет свои собственные классы миграции. С помощью псевдонимов вы можете привязать классы Groovy-migration-class к реальным java-классам.
  2. Создание классов рефакторинга для сложных сценариев. Также свяжите эти классы с псевдонимами .
10
ответ дан 5 December 2019 в 14:02
поделиться

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

Вы делаете странное сравнение: если вы хотите выполнить «горячую миграцию» базы данных, вам, вероятно, придется выполнить x + 1 , x + 2 подход к управлению версиями, который вы описали, но я действительно не знаю - я бы тоже не знал, как это сделать с SQL, поскольку я не эксперт по базам данных.

Если вы мигрируете «холодным» способом, вы можете просто сделать это за один шаг, создав экземпляр нового объекта из старых данных, сохранив новый объект, удалив старый объект для каждого объекта в хранилище. См. ссылку на db4o .

Но, честно говоря: тот же процесс в СУБД также сложен, потому что вам придется деактивировать проверки ограничений (и, возможно, триггеры и т. Д.), Чтобы фактически выполнить операцию - возможно, не в приведенном вами примере, но для большинства реальных случаев. В конце концов, разделить струны так легко, что будет мало выигрыша.

В SQL я бы просто заполнил столбцы «first_name» и «second_name»

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

Для этого вам тоже придется написать код.

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

2
ответ дан 5 December 2019 в 14:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: