Запретить потерянные объекты в DB4O при обновлении полей - PullRequest
1 голос
/ 04 марта 2010

Я хочу хранить объекты Person в DB4O. Поле «Местоположение человека» может быть изменено с течением времени. Поэтому я извлекаю человека из БД и вызываю метод для установки поля местоположения в новый объект Местоположение. (Я хочу, чтобы объекты Location были неизменными, т. Е. Объекты значений DDD).

Это работает, однако ранее назначенные объекты Location остаются в базе данных. Как я могу настроить DB4O для удаления этих потерянных объектов Location? Или мне нужен какой-то специальный процесс для сборки мусора?

Упрощенные классы для этого примера:

class Person {
    Location location;
    public void Move(Location newLocation) { 
        location = newLocation;
    }
}

class Location {
    public Location(string city) { 
        this.City = city;
        //etc
    }
    public readonly string City;
    /// more fields...
}

РЕДАКТИРОВАТЬ: Еще немного информации - Person должен быть агрегатным корнем DDD. Таким образом, нет никаких внешних ссылок на внутреннее состояние человека. Если Person обновляет свое местоположение, то старое местоположение должно прекратиться.

Ответы [ 5 ]

1 голос
/ 08 марта 2010

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

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

configuration.common().objectClass(Person.class).objectField("location").cascadeOnDelete(true);

Теперь нам нужно обработать случай изменения местоположения. Идея такова:

  1. Зарегистрируйтесь для активации события. Там вы «помните», какой объект был внедрен
  2. Зарегистрируйтесь на update-событие. Там вы проверяете, если это все тот же встроенный объект. Если нет, вы удаляете старое вкл.
  3. Очень важно: никогда не «делиться» встроенным объектом, иначе он будет удален для всех. Простое решение - создать копию объекта Location при каждом назначении.

Существует Java-демонстрация, в которой реализует это поведение .

Ну, это всего лишь концепция, это долгий путь к приемлемому решению:

  1. Использовать атрибуты или другую конфигурацию, чтобы указать, какие объекты являются такими
  2. Создание надежной реализации обработчиков событий и т. Д.
  3. Надежное решение, гарантирующее, что «общее» местоположение не будет удалено
0 голосов
/ 09 октября 2012

Согласно справке API db4o 8.0 cascadeOnDelete (логическое значение) , старый объект должен быть удален автоматически. Вот копия документа, проверьте приведенный пример.

sets cascaded delete behaviour. 

Setting cascadeOnDelete to true will result in the deletion of all member objects of instances of this class, if they are passed to ObjectContainer.delete(Object). 

Caution !
This setting will also trigger deletion of old member objects, on calls to ObjectContainer.store(Object).

An example of the behaviour:

ObjectContainer con;
Bar bar1 = new Bar();
Bar bar2 = new Bar();
foo.bar = bar1;
con.store(foo); // bar1 is stored as a member of foo
foo.bar = bar2;
con.store(foo); // bar2 is stored as a member of foo 

The last statement will also delete bar1 from the ObjectContainer, no matter how many other stored objects hold references to bar1. 

The default setting is false.

In client-server environment this setting should be used on both client and server. 

This setting can be applied to an open object container. 

Parameters:
flag - whether deletes are to be cascaded to member objects.
See Also:
ObjectField.cascadeOnDelete(boolean), ObjectContainer.delete(Object), Using callbacks

Однако это не работает так, как напечатано, странно.

0 голосов
/ 04 марта 2010

Вы думали о том, чтобы сделать его типом значения?

0 голосов
/ 06 марта 2010

Это действительно выглядит как транзакция для меня.

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

В СУБД для этого вам также потребуется выполнить транзакцию. Однако многие системы РСУБД поддерживают вас здесь с помощью триггеров и событий. Обратите внимание, что db4o также предлагает определенные обратные вызовы.

В настоящее время я работаю над абстракцией ref-count для таких случаев, как это сложно сделать в общем. С другой стороны, вы можете написать специальный метод Update, который упростит транзакцию для вас и сравнит ссылки на старые и новые объекты. Если они не совпадают, и вы можете быть уверены, что никто другой не ссылается на этот тип объекта адреса, вы можете удалить его.

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

Эта концепция «совокупного корня» мне кажется очень расплывчатой ​​- в конце концов, это зависит от перспективы, но это другая проблема.

0 голосов
/ 04 марта 2010

Как насчет использования db4o delete() сначала в старом месте, а затем в сохранении нового?

Best!

Немецкий

...