2010-03-10 15 views
8

Jedną z rzeczy, które ciągle uważam za bardzo mylące w używaniu bazy danych obiektów takich jak db4o jest sposób obsługi złożonych migracji, które normalnie byłyby obsługiwane przez SQL/PL-SQL.Obsługa przechowywania danych w bazach danych obiektów takich jak db4o

Na przykład wyobraź sobie, że masz tabelę w relacyjnej bazie danych o nazwie my_users. Oryginalnie miałeś kolumnę o nazwie "full_name", teraz, gdy twoje oprogramowanie jest w wersji V2, chcesz usunąć tę kolumnę, podzielić pełne nazwy na puste miejsce i umieścić pierwszą część w kolumnie o nazwie "first_name", a drugą w kolumnie o nazwie last_name. W SQL po prostu wstawiłbym kolumny "first_name" i "second_name", a następnie usunąłem oryginalną kolumnę o nazwie "full_name".

Jak to zrobić w coś w stylu db4o? Czy piszę program w Javie, który skrypty wyszukują wszystkie obiekty User.class, ustawiając full_name na null podczas ustawiania first_name i last_name? Kiedy wykonuję następną komendę svn commit, nie będzie właściwości field/bean odpowiadającej full_name, czy byłby to problem? Wygląda na to, że używając go w aplikacji produkcyjnej, gdzie mój "schemat" się zmienia, chciałbym napisać skrypt do migracji danych z wersji x do wersji x + 1, a następnie w wersji x + 2 faktycznie usunąć właściwości, które próbuję pozbyć się wersji x + 1, ponieważ nie mogę napisać skryptu Java, aby zmodyfikować właściwości, które nie są już częścią mojego typu.

Wydaje się, że częścią problemu jest to, że RDBMS postanawia co obiekt, który powołując się na podstawie niewrażliwego nazwy strun opartych na prostym przypadku, w języku, jak wpisywanie Java jest bardziej skomplikowana, niż to, że nie może odnosić się do własność, jeśli getter/setter/field nie jest członkiem klasy załadowanej w środowisku wykonawczym, więc zasadniczo musisz mieć 2 wersje kodu w tym samym skrypcie (hmm, niestandardowe programy ładujące klasy brzmią jak ból), mieć nową wersję twojego przechowywane klasy należą do innej paczki (brzmi niechlujnie), lub użyj strategii x + 1 x + 2, o której wspomniałem (wymaga o wiele więcej planowania). Być może jest jakieś oczywiste rozwiązanie, którego nigdy nie udało mi się zebrać z dokumentów db4o.

Wszelkie pomysły? Mam nadzieję, że ma to jakiś sens.

Odpowiedz

10

Najpierw db4o obsługuje "prosty" scenarios like adding or removing a field automatically. Podczas dodawania pola cały istniejący obiekt ma zapisaną wartość domyślną. Po usunięciu pola dane istniejącego obiektu nadal znajdują się w bazie danych i nadal można uzyskać do niego dostęp. Zmiana nazwy pola itp. To special 'refactoring'-calls.

Teraz Twój scenariusz byś zrobił coś takiego:

  1. Usuń polu 'FULL_NAME', należy dodać nowe pola 'first_name' oraz 'second_name'
  2. iteracyjne ponad wszystko „Address'-objects
  3. Uzyskaj dostęp do starego pola za pomocą interfejsu API "StoredClass"
  4. Podziel, zmień, zaktualizuj itp. Wartość. Ustaw nowe wartości w nowym polu i zapisz obiekt.

Załóżmy, że mamy klasę "Adres". Pole "full_name" zostało usunięte. Teraz nie będziemy go kopiować do "imienia" i "nazwiska". To może iść tak (Jawa):

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); 
    } 

Jak zasugerował, że piszesz z migracją kodu dla każdej wersji burzliwemu. To pole nie jest już częścią twojej klasy, musisz uzyskać do niego dostęp za pomocą "StoredField'-API jak wyżej".

Możesz otrzymać listę wszystkich "przechowywanych" klas z ObjectContainer.ext().storedClasses(). Za pomocą StoredClass.getStoredFields() możesz otrzymać listę wszystkich pól magazynu, nie ma już pola, które nie istnieje już w twojej klasie. Jeśli klasa już nie istnieje, nadal możesz uzyskać obiekty i uzyskać do nich dostęp za pośrednictwem klasy "GenericObject".

Aktualizacja: dla scenariuszy kompleksowych, w przypadku których baza danych musi zostać poddana migracji w wielu etapach.

Na przykład w wersji v3 obiekt adresowy wygląda zupełnie inaczej. Tak więc "skrypt migracyjny" dla wersji od 1 do 2 nie ma już wymaganych pól (imię i nazwisko w moim przykładzie). Myślę, że istnieje wiele możliwości radzenia sobie z tym.

  1. (Przy założeniu Java dla tego pomysłu. Oczywiście istnieje odpowiednik w .NET). Możesz wykonać krok migracji jako Groovy-script. Więc każdy skrypt nie ingeruje w inny. Następnie definiujesz "klasy" potrzebne klasy dla migracji tam. Każda migracja ma własne klasy migracji. Z aliases powiążesz swoje klasy migracji groovy z rzeczywistymi klasami java.
  2. Tworzenie klas refaktoryzacji dla złożonych scenariuszy. Połącz również te klasy z aliases.
2

Robię tu trochę dzikiego strzału, ponieważ nie zmodyfikuję zbyt wiele danych w moim życiu.

Dokonujesz dziwnego porównania: Jeśli chcesz "migrację na gorąco" bazy danych, prawdopodobnie będziesz musiał wykonać opisane przez ciebie podejście do wersji x+1, x+2, ale tak naprawdę nie wiem - nie chciałbym Wiesz, jak to zrobić z SQL, ponieważ nie jestem ekspertem od db.

Jeśli migrujesz "na zimno", możesz zrobić to w jednym kroku, tworząc nowy obiekt ze starych danych, zapisać nowy obiekt, usunąć stary obiekt dla każdego obiektu w sklepie. Zobacz db4o reference.

Ale szczerze: ten sam proces w RDBMS jest również skomplikowany, ponieważ będziesz musiał dezaktywować kontrole więzów (i ewentualnie wyzwalacze itp.), Aby faktycznie wykonać operację - być może nie w podanym przykładzie, ale w większości przypadków w świecie rzeczywistym. W końcu podział łańcuchów jest tak łatwy, że będzie niewielki zysk.

W SQL Chciałbym po prostu zapełnić "imię" i "second_name" kolumn

Tak, z prosty działania podzielonego ciąg, można prostu zrobić. Jednak w typowym scenariuszu refakturowania zmieniasz strukturę obiektów na podstawie dużych i skomplikowanych zestawów reguł, które mogą nie być łatwe do wyrażenia w SQL, mogą wymagać złożonych obliczeń lub zewnętrznych źródeł danych.

Aby to zrobić, trzeba też napisać kod.

W końcu nie widzę zbyt dużej różnicy w obu procesach. Zawsze będziesz musiał uważać na dane na żywo, a na pewno zrobisz kopię zapasową w obu przypadkach. Refaktoryzacja jest fajna, ale wytrwałość jest trudna, więc synchronizacja jest wyzwaniem w każdym przypadku.