Sprawdzanie różnic w obiekcie przed zapisem do bazy

0

Hej,
zastanawiam sie nad podejściem do problemu rejestrowania zmian na obiekcie bazodanowym.
Ktoś pracuje na obiekcie pobranym z bazy, wykonuje modyfikacje no i w momencie zapisu musimy gdzieś zapisać informacje w stylu: "Jan Nowak 25 lipca 2020 roku zmienił nazwisko na "kowalski", itd.
Tego typu logi musimy zapisywać. Zastanawiam sie jak podejść do tematu rejestrowania różnic.

Mam dwa pomysły:

  1. w momencie modyfikacji poszczególnych kolumn rejestrować, ze obiekt jest dirty, robić listę zmian. i przy zapisie je również zapisywać
  2. w momencie zapisu do bazy pobieramy kopie obiektu z bazy, robimy jakiegoś diffa i zapisujemy listę zmian

Jakies inne pomysly?
Pozdr

0

W punkcie pierwszym jak nie pobierzesz danych z bazy to nie będziesz wiedział co zmieniasz, finalnie możesz skończyć na "zmieniono Kowalski na Kowalski"
Punkt drugi to bardziej naturalny sposób, bierzesz obiekt, modyfikujesz go i zapisujesz go wraz z różnicami. Tutaj unikasz zarówno bezsensownego logu i jak i w ogóle nie musisz obiektu zapisywać, bo wiesz że go nie zmieniono.

Są ORM'y które pobrany obiekt przy modyfikacji określają jako zmodyfikowany lub nie w zależności czy faktycznie nastąpiła modyfikacja. Wtedy odpada pisanie porównywacza, który wymagać będzie trochę pracy i trzeba napisać go mocno uniwersalnie, w przeciwnym wypadku będziesz musiał dla każdej nowej encji i typu dopisywać nowy "porównywacz".

Są też audyty bazodanowe, które zrobią to automatycznie za Ciebie.

Wracając to co chcesz mieć
"Jan Nowak 25 lipca 2020 roku zmienił nazwisko na "kowalski", itd.
jeśli nie znajdziesz jakiejś biblioteki i tak trzeba będzie napisać na piechotę.

I jeszcze ostatnie - docelowo lepiej nazywać zmiany uniwersalnie
Kto | Kiedy | Przed | Po w jakiejś formie tabelarycznej, chyba że chcesz się męczyć z językiem polskim "zmienił, zmieniła, zmieniono"

0

A z czego korzystasz? Jaki framework? Bo np w takim laravelu jest prosty mechanizm observerów, gdzie takie coś robisz w 5 minut.

0

Pytanie jest inne - czy musisz to robić po stronie bazy?
Bo jeszcze jest opcja (dla mnie - bardziej logiczna) żeby tego pilnować po stronie aplikacji. W sensie - skoro zmieniasz dane (np. dane klienta) to musisz je w jakimś formularzu wyświetlić. Więc - wyświetlając je, możesz zapisać ich pierwotną wartość gdzieś w apce. A potem - jak user klika "Zapisz" to porównujesz wartość pół, które się zmieniły i przesyłasz odpowiednią informację do bazy.

W sensie - dajesz dwa równoległe zapisy: jeden z nowymi danymi, drugi z listą zmian.

Jeśli się obawiasz o to, że jedno się zapisze, a drugie nie - możesz to opakować w jakąś transakcję.

Zastanów się nad jeszcze jednym scenariuszem:

  • user A otwiera do edycji kartotekę klienta X
  • user B po chwili robi to samo
  • B poprawia numer mieszkania z 7 na 9
  • A poprawia numer mieszkania z 7 (które pobrał pierwotnie z bazy i które jest u niego pamiętane jako wartość pierwotna) na 12
  • w efekcie masz w bazie zapisaną wartość mieszkania na 12
  • a w logach masz takie zmiany: B zmienił z 7 na 9, A zmienił z 7 na 12.

Dlatego trzeba jakoś to rozwiązać. Najlepszą opcją jest blokowanie danego rekordu/przełączanie w tryb tylko do odczytu w chwili, gdy inny operator go edytuje. Jest to czasem irytujące dla użytkowników, ale zapewnia największą pewność, żę posiadane dane będą spójne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1