2010-03-04 7 views
1

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

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

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

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... 
} 

EDIT: Некоторые больше информации - Person предназначается, чтобы быть совокупный корень DDD. Таким образом, нет внешних ссылок на внутреннее состояние человека. Если Person обновляет свое местоположение, старое местоположение должно перестать существовать.

+0

wtf is DDD dawg –

ответ

1

Я думаю, что нет идеального решения. Но с некоторой работой вы можете почти достичь такого поведения. Аналогичная тема - already discussed here.

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

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

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

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

Существует Java-Demo, который implements this behavior.

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

  1. использовать атрибуты или другую конфигурацию, чтобы указать, какие объекты являются такими
  2. построить надежную реализацию обработки событий и т.д.
  3. Твердый раствор, чтобы гарантировать, что «общий» местоположение не удаляется
+0

Это отличный ответ. Я занимаюсь расследованием событий, чтобы сделать именно это. Я рад, что мы согласны с тем, что это жизнеспособный подход. –

0

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

Лучшее!

Немецкий

+0

Я сделал образец кода более представительным для моей ситуации. Поле местоположения является приватным. Я хочу, чтобы слой persistence автоматически удалял старый объект местоположения. В противном случае я должен начать копаться в каждом объекте, просто чистить вещи. –

0

Считаете ли вы, что это тип ценности?

+0

Мне не нужно начинать использовать структуры повсюду ниже объекта верхнего уровня. –

+0

Да, это может быть беспорядок ... они должны добавить способность обрабатывать ссылочный объект как тип значения из перспективы базы данных. – 2010-03-05 18:00:13

0

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

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

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

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

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

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

+0

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

+0

Это означает, что вы предполагаете, что ваши объекты местоположения никогда не ссылаются ни на что другое? Я все еще не чувствую, что удаление объектов должно происходить в какой-то скрытой, автоматической манере, но это, похоже, в основном зависит от вкуса - ведь сборка мусора - это крутая функция. Лично я не готов к такой функции на сохраненных данных. – mnemosyn

0

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

 
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 

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