Foreign key w kilku tabelach i jego update

0

Siema,

Mam pewien przypadek, który w sumie ciężko mi znaleźć w google:

Co mam:
Mam aplikację webową, używam Hibernate i Oracle. Mam sobie tabelę dajmy na to users i tam pod id = 5 jest jakiś Stefan. Mam również tabele B i C, i obie mają foreign keya do tabeli users, obecnie w tych tabelach jest tylko po jednym wierszu, i w obu przypadkach ten FK wskazuje na id = 5, czyli na Stefana.

No i teraz co się dzieje (akcja):
W tabeli B zmieniam pointera do użytkowników na id = 7, i od teraz w tabeli B mam, powiedzmy, Andrzeja.

Co chcę osiągnąć:
Chcę, żeby po updejcie tabeli B, wiersz w tabeli C zaczął automatycznie również wskazywać na Andrzeja.

Założenia:

  1. Podczas zmiany ze Stefana na Andrzeja w tabeli B, nic nie wiem że w ogóle istnieje tabela C
  2. Oczywiście tak naprawdę w tabeli B i C mam więcej niż jeden rekord, ale napisałem to tylko w celach uproszczenia
  3. Wolałbym ominąć triggery

Rzadko tu piszę i nie wiem kto tu się często udziela, ale domyślnie zawołam celebrytę @Shalom :D

1

A znalazłeś ten wątek? ;)

Motyw był taki

  • coś ląduje / zmienia się w tabeli
  • po tym jak coś wyląduje w tabeli ma się wykonać jakaś akcja (update)
  • architekt zabronił użycia triggerów
  • zmiany nie musiały być wprowadzane natychmiast

Moja wiedza o Oracle SQL jest dokładnie zerowa, ale może faktycznie byłbyś w stanie wykorzystać choćby CQN by ten 'nasłuchiwał' zmian w tabeli B i odpalał odpowiedni update tabeli C?

Ewentualnie, może w Twoim use case jesteś w stanie użyć computed column tak, by kolumna z ID w tabeli C była obliczana jakimś subquery z tabeli B? Będzie wprawdzie read-only, ale gdyby miała się updatować tylko wtedy, gdy coś się zmienia w B no to...

BTW. to są tylko takie moje luźne pomysły i nie ręczę, że są cokolwiek warte, żeby nie było :D

0

A kto wg hibernate jest "właścicielem" tej relacji?

0
Shalom napisał(a):

A kto wg hibernate jest "właścicielem" tej relacji?

Nie mam nigdzie ustawionego mappedBy. Mam coś takiego (w encji do tabeli C):

@OneToOne
    @JoinColumn(name = "user_fk", nullable = false)
    @Setter(NONE)
    private User user;
0

Ech triggerem after update i podbijasz wartości FK wtedy kiedy w tabeli się zmieni.

1

Może zmień model ;-)

Jak rozumiem struktura jest taka:

User
  +--FK--Tab_A
  +--FK--Tab_B
  +--FK--Tab_C

Może nie trzymaj tej relacji bezpośrednio tylko pośrednio, np.

User----User_Link
             +--A
             +--B
             +--C

Jak zmieniasz Stefana na Andrzeja, to tylko aktualizujesz User_Link, a FK z A/B/C do User_Link pozostają bez zmian.

2

Może napisz jakie ma być praktyczne zastosowanie tej zmiany. Bo ten sposób co zaprezentowałeś, to nie jest dobra sprawa :)
Tracisz informację, że w jakimś okresie był przypisany user o ID=5.

W takich przypadkach - niech to będzie np. cesja umowy z użytkownika nr 5 na użytkownika nr 7, zapisuje się historię tego obiektu. Czyli albo gdzieś oddzielnie trzymasz informację, że od momentu A do B stroną umowy był Stefan, a od momentu B+1 Andrzej. Możesz też to zrobić w tej samej tabeli dodając do niej daty obowiązywania danego związku z userem.

Samomodyfikujące się dane w bazie to pierwszy krok do kłopotów.

0
yarel napisał(a):

Może nie trzymaj tej relacji bezpośrednio tylko pośrednio, np.

User----User_Link
             +--A
             +--B
             +--C

Jak zmieniasz Stefana na Andrzeja, to tylko aktualizujesz User_Link, a FK z A/B/C do User_Link pozostają bez zmian.

Jak zrobić taki link? co to jest i jak to wygląda? Osobna tabela jakaś?

robertos7778 napisał(a):

Może napisz jakie ma być praktyczne zastosowanie tej zmiany. Bo ten sposób co zaprezentowałeś, to nie jest dobra sprawa :)

Biznes case jest taki:
Tabela B trzyma info o tym, jaki user jest odpowiedzialny za pewną rzecz. W tabeli C chcę trzymać info co do wysyłania powiadomień e-mail. I chcę wysyłać na adres usera odpowiedzialnego za pewną rzecz, z tabeli B. I w tabeli C chcę trzymać referencję do usera, któremu wysyłać maila.

0

Dobra panowie, dziękuję za odpowiedzi, jednak zmieniam w ogóle podejście i problem zniknie ;)

0

Biznes case jest taki:
Tabela B trzyma info o tym, jaki user jest odpowiedzialny za pewną rzecz. W tabeli C chcę trzymać info co do wysyłania powiadomień e-mail. I chcę wysyłać na adres usera odpowiedzialnego za pewną rzecz, z tabeli B. I w tabeli C chcę trzymać referencję do usera, któremu wysyłać maila.

Ja tu widzę inny problem, jeśli C to ustawienia powiadomień mailowych dla jakichś rzeczy z B, to dlaczego C jest powiązane z A a nie z B? Nawet, jeśli te ustawienia powiadomień zależą np. od preferencji konkretnego użytkownika, a nie od case'a, to i tak nie ma chyba sensu przepinać cudzych preferencji na nową osobę - a jeśli zależą od tego, co się dzieje w B, to też średnio jest sens dublować tam userid, skoro i tak wiadomo że jak Marian za coś odpowiada, to nie będziesz tym zawracać głowy Marzenie ;)

0
Pinek napisał(a):

Biznes case jest taki:
Tabela B trzyma info o tym, jaki user jest odpowiedzialny za pewną rzecz. W tabeli C chcę trzymać info co do wysyłania powiadomień e-mail. I chcę wysyłać na adres usera odpowiedzialnego za pewną rzecz, z tabeli B. I w tabeli C chcę trzymać referencję do usera, któremu wysyłać maila.

No to jeśli zmieniasz przypisanie przedmiotu do osoby, to zachowaj historię. Czyli nie nadpisuj klucza, a "zamknij" daną przynależność (zmień status, ustaw datę końca obowiązywania, przenieś do tabeli historycznej, ...), a dodaj nowy rekord z informacją, że teraz drugi użytkownik ma przypisaną tę rzecz. Prędzej czy później dysponent biznesowy przychodzi z pytaniem typu "a czy moglibyśmy dostać zestawienie, kto najdłużej miał przypisaną daną rzecz albo jaki był średni czas przypisania przedmiotu do osoby".
Nadpisanie klucza obcego niszczy informację bezpowrotnie i trzeba tego unikać. Robi się to raczej w trybie serwisowym, gdy coś okazuje się błędnie przypisane do innego rekordu.

0
robertos7778 napisał(a):
Pinek napisał(a):

Biznes case jest taki:
Tabela B trzyma info o tym, jaki user jest odpowiedzialny za pewną rzecz. W tabeli C chcę trzymać info co do wysyłania powiadomień e-mail. I chcę wysyłać na adres usera odpowiedzialnego za pewną rzecz, z tabeli B. I w tabeli C chcę trzymać referencję do usera, któremu wysyłać maila.

No to jeśli zmieniasz przypisanie przedmiotu do osoby, to zachowaj historię. Czyli nie nadpisuj klucza, a "zamknij" daną przynależność (zmień status, ustaw datę końca obowiązywania, przenieś do tabeli historycznej, ...), a dodaj nowy rekord z informacją, że teraz drugi użytkownik ma przypisaną tę rzecz. Prędzej czy później dysponent biznesowy przychodzi z pytaniem typu "a czy moglibyśmy dostać zestawienie, kto najdłużej miał przypisaną daną rzecz albo jaki był średni czas przypisania przedmiotu do osoby".
Nadpisanie klucza obcego niszczy informację bezpowrotnie i trzeba tego unikać. Robi się to raczej w trybie serwisowym, gdy coś okazuje się błędnie przypisane do innego rekordu.

Hmm nie, akurat w moim przypadku taka historia nie jest konieczna, ale dzięki za post ;)

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