JPA ciekawskie pytania odośnie relacji i nie tylko

0

Witam

Mam takich kilka pytań czysto teoretycznych.

**I )**Chodzi mi o dwukierunkową relację jeden do wielu.
Otóż jak wiadomo w takiej relacji stroną właścicielską jest ta encja która nie zawiera kolekcji.

Ja sobie zrobiłem taki mały trick. Mam pierwszą klasę która zawiera kolekcje

    @OneToMany(cascade=CascadeType.ALL , mappedBy="person" , fetch=FetchType.EAGER)
   private List<Info> infos = new ArrayList<Info>();

natomiast w 2 klasie mam :

	@ManyToOne(optional=false ,cascade= CascadeType.ALL)
	@JoinColumn(name = "personid", referencedColumnName="id")
    private Person person;

Wszystko ładnie i pięknie. Chcę jednak mieć możliwość przy utrwalaniu encji person utrwalić wszystkie elementy kolekcji info. Więc wykonałem takie 2 małe tricki :

  1. W konstruktorze :
public Person(String name, String lastName, List<Info> infos){
	this.name = name; 
	this.lastName = lastName; 
	for(Info i : infos){
		i.setPerson(this);
	}
	this.infos = infos;
}

  1. utworzyłem podobną metodę która iteruje liste...

Tylko zastanawiam się czy A) To jest poprawne B) czy potrzebne jest this.infos = infos (po utrwaleniu encji automatycznie powinienem odczytywać te wartości )??

II) Moje 2 pytanie jest też z tej samej beczki. Chodzi mi o tworzenie encji, czasami przeglądam kod innych osób i przy tworzeniu encji dodają one generowanie id choćby w ten sposób :

@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)

następnie tworzą konstruktora oraz settera dla tego id:

public Person(Integer id , String name .......){
this.id = id;}

//settter

Może to jest głupie pytanie, ale nie bardzo rozumiem dlaczego ? przecież id jest generowane przez bazę więc po co dawać możliwość programowej zmiany tej wartości ??

III)
I moje ostatnie pytanie też może dziwne. Zauważyłem, że niektórzy ale nie wszyscy programiści tworząc encję piszą metodę equals która porównuje wszystkie pola danej encji. Natomiast ja , oraz jak widziałem inni, tworzę metodę equals w JEE na takiej zasadzie, że porównuję tylko klucze. Wychodząc z założenia, że klucz musi być unikatowy... .

Czy dobrze rozumuję ??

Takie o to myśli mnie dręczą, niby dla niektórych proste ale jednak chciałbym mieć pewność czy dobrze rozumuję.

0

TL;DR
Ale na ostatnie pytanie moge odpowiedziec - a co jesli wywolujesz metode equals z obiektorem ktory jeszcze nie ma klucza obcego (ktory jak sam zauwazyles u ciebie generuje baza, zatem dopiero jest dostepny po zapisie?) Np. masz osobe i ona ma zbior adresow, i jest to hashset, i dodajesz nowy adres do zbioru i musisz obliczyc i hash i jesli sie okaze ze jest juz taki hash, to wywolywana jest metoda equals? W twoim przypadku leci NPE albo dostajesz blad przy porownywanie, zalezy co this a co jest argumentem do equals...

0

Nie wiem czy na tym forum nie ma nikogo kto może mi odpowiedzieć na te pytania. Przecież są tutaj chyba osoby które na co dzień piszą aplikacje klasy EE .

Jak widzę czasami proste pytanie rodzi brak odpowiedzi :/

0

Tak, dlatego nie uzywa sie kluczy do powownywania wlasnie z powodu ze zmienia sie wynik. Jesli nie widzisz sensu powownywania nie zapisanej encji z zapisana no to juz twoj problem, zauwaz jednak ze podalem pierwszy lepszy przyklad gdzie to jest potrzebne.
Aby uniknac takich problemow uzywa sie 'danych biznesowych' encji a nie klucza - wtedy metody zwracaja ten sam wynik bez wzgledu na to czy zapisane czy nie.

1

I "Tylko zastanawiam się czy A) To jest poprawne B) czy potrzebne jest this.infos = infos".
A) Jest poprawne. Jedyną rzeczą, do której można się przyczepić to fakt, że przed końcem konstruktora, pozwalasz, aby referencja do tego obiektu (this) została przekazana do innej klasy
B) Najlepiej zawsze ustawiać relację z obu stron. Jeżeli tego nie zrobisz, a będziesz próbował skorzystać z encji Person w tej samej transakcji, to pole to będzie miało niepoprawną wartość (null lub pusta lista).
II Trzeba być bardzo ostrożnym przy ustawianiu id w encji @GeneratedValue. Można ją podłączyć do sesji za pomocą merge(), ale nie można wykonać persist().
III Jeżeli używasz zbioru (np. HashSet) i zdefiniujesz funkcję equals bazującą jedynie na id, to do tego zbioru nie będzie można dodać dwóch nowych obiektów (oba będą mieć id=null).

1

Pytanie o Person i Info - jako ze info zarzadza kluczem, czyli relacja, musisz zadbac aby w info byl ustawiony odpowiedni Person, np. tak jak to zrobiles. Sa tez inne sposoby - np. Person ma metody addInfo, removeInfo (tak, przy usuwaniu musisz zadbac o wyzerowanie referencji do person) itp. Tam, dodajesz Info do kolekcji, oraz ustawiasz Info.setPerson(this) (pseudokod). To jest standard - przeciez chcesz miec spojny graf obiektow - skoro jest to relacja dwukierynkowa, to jak person ma info, to to info musi tez wskazuwac na to person. (Przy wczytywaniu z bazy jpa zadba tak czy tak, ale ty powinienes ten graf miec poprawny rozniez przed zapisem, albo w trakcie jego edycji).
W Info.setPerson byl rowniez wywolal Person.addInfo(this) - tutaj widzisz pewien problem ze dojdzie do cycklu wywolan - ja rozwiazuje to tak ze daje dodatkowe 2 metody ktore maja widocznosc pakietu:

Person:

public addInfo(Info i) { infos.add(i); i.setPersonInternal(this); }
addInfoInternal(Info i) { infos.add(i); }

Info:

public setPerson(Person p) { this.person = p; p.addInfoInternal(this); }
setPersonInternal(Person p) { this.person = p; }

W ten sposob lamiesz cykl - ok, troszke wiecej kodzenia, ale zawsze spojny model.

Bardzo rzadko robie relacje dwukierunkowe, jakos tak doswiadczenie moje wskazuje ze nie jest to najczesciej potrzebne.

0

Kopia z komentarza:

No tak tylko, że w środowisku JEE jeśli porównasz 2 encje po kluczu to te encje muszą Ci się zgadzać. Przecież w bazie danych nie mogą istnieć 2 encje o takim samym kluczu. Dlatego wydaje mi się sensowne porównywanie 2 encji za pomocą metody equals. Tak jak napisałem spotkałem się z takimi przypadkami, że różnie ludzie implementowali tą metodę w encji dlatego pytam. Jaki jest standard. Ja piszę tak jak ja to rozumuję

Nie rozumiem co tu piszesz, musisz pisac jasniej, inaczej sie gubie... Wiadomo ze 2 encje nie moga miec takiego samego klucza, ale zakladanie ze zawsze bedziesz porownywal encje ktore maja juz jakis klucz (zakladajac rowniez ze jest on generowany przez baze, czyli twoje encje zawsze sa juz zapisane) swiadczy o 1 z 2: a. masz zajebiscie prosty projekt, np. taki ktory sluzy tylko do odczytu z bazy (zazdroszcze ci troche ;d) b. nie znasz wszystkich wymagan. equals i hashCode sa dosc podstawowymi funkcjami, i jak je spaprzesz na poczatku, pozniej moze byc ciezko. Np. taki use case: tworzysz Osobe i dodajesz jej 2 KartyKredytowe (to jest HashSet<KartaKredytowa>); zadna z encji nie jest odczytana z bazy, tylko wszystkie sa nowe - po zapisie sie okazuje ze Osoba ma tylko 1 karte. Dlaczego? Bo dodanie do hashsetu 2 encji z tym samym hashem (liczonym z tej samej wartosci - null z nie wygenerowane jeszcze id) doda tylko ta pierwsza: hash bedzie taki sam, nastepnie wywolana zostanie equals, ktora rowniez bazuje na tej samej wartosci (nie wygenerowane id).

0
__krzysiek85 napisał(a):

A) Jest poprawne. Jedyną rzeczą, do której można się przyczepić to fakt, że przed końcem konstruktora, pozwalasz, aby referencja do tego obiektu (this) została przekazana do innej klasy

No tak co do B też się zgodzę. Racja jeśli w 1 transakcji będę się chciał odwołać do zbioru to otrzymam null.
A)Robię tak dlatego, że w JPA narzuca rozwiązanie w którym w przypadku relacji jeden do wielu dwukierunkowej stroną właścicielską jest komponent z licznością równą 1. Gdybym nie dodał tej metody reprezentacja modyfikowanej relacji na poziomie bazy danych nie zostanie zaktualizowana. (EJB Helion str. 169)
Jeśli bym tego nie zrobił i zaimplementowałbym usługę która zapisuje tą encję np save to w tej funkcji musiałbym i tak dla każdego elementu info wywoływać metodę info.setPerson( "person"). Czyli to samo tylko musiałbym o tym pamiętać, że muszę taką metodę zaimplementować .

Weźmy przykład, że tworzę sobie gdzieś tam w kontrolerze swoją osobę , mam sobie wstrzyknięte PersonDAO i następnie chcę ją utrwoalić:

......

@Autowired
private PersonDAO personDao;

...
String name = //get name np z forumularza itd
String lastName = .....

Info a , b...

Person p = new Person(name, lastName, infos);
//Jeśli zrobię pętlę w konstruktorze to mogę się odwołać np 
// b.getPerson();
// jeśli nie to dostane null

personDao.save(person);


Więc moja funkcja musiała by wyglądać w ten sposób: oko


public void save Person(Person person){

	List<Info> infos = person.getInfos();
	for(Info i : infos){
		i.setPerson(person);
	}
	entittyManager.persist(person);

}

Jeśli opuściłbym pętlę for hibernate rzuci mi Null not allowed for column person_id
Rożnica jak dla mnie jest taka, że w moim przypadku jeśli dodam sobie to do konstruktora, to nie muszę się martwić o implementacje tego w metodzie biznesowej.
Takie jest przynajmniej moje rozumowanie.

0

Nie rozumiem co tu piszesz, musisz pisac jasniej, inaczej sie gubie... Wiadomo ze 2 encje nie moga miec takiego samego klucza, ale zakladanie ze zawsze bedziesz porownywal encje ktore maja juz jakis klucz (zakladajac rowniez ze jest on generowany przez baze, czyli twoje encje zawsze sa juz zapisane) swiadczy o 1 z 2: a. masz zajebiscie prosty projekt, np. taki ktory sluzy tylko do odczytu z bazy (zazdroszcze ci troche ;d) b. nie znasz wszystkich wymagan. equals i hashCode sa dosc podstawowymi funkcjami, i jak je spaprzesz na poczatku, pozniej moze byc ciezko. Np. taki use case: tworzysz Osobe i dodajesz jej 2 KartyKredytowe (to jest HashSet<KartaKredytowa>); zadna z encji nie jest odczytana z bazy, tylko wszystkie sa nowe - po zapisie sie okazuje ze Osoba ma tylko 1 karte. Dlaczego? Bo dodanie do hashsetu 2 encji z tym samym hashem (liczonym z tej samej wartosci - null z nie wygenerowane jeszcze id) doda tylko ta pierwsza: hash bedzie taki sam, nastepnie wywolana zostanie equals, ktora rowniez bazuje na tej samej wartosci (nie wygenerowane id).

Ok to daje mi do myślenia. Jeśli mogę się wytłumaczyć to wcześniej pracowałem na projekcie w którym założeniem było, że nie utrwala się klas które zawierały kolekcje i relacje typu @OneToMany @ManyToOne itp ...

Tworzyło się klasę np Person zawierającą tyko podstawowe pola typu String, int itd . Oraz tworzyło się Klasę np FPerson gdzie były relacje . Np:


public class FPerson {

.......

@OneToMany
@JoinColumn(name="person_id")
public List<Infos> infos;
......
}

I Klasa Person służyła do zapisywania encji natomiast klasa FPerson stanowiła jej logiczne powiązanie + dodatkowe informacje dzięki którym odczytywało się info odnośnie tej klasy oraz innych składowych, które wchodziły w relacje z daną klasą. Więc dlatego też programiści doszli do wniosku, że wystarczy porównywanie tylko po kluczu, ponieważ projekt nie przewidywał możliwości utrwalania encji która zawierałaby takie powiązania. Pewnie niektórzy się zastanowią jak w takim razie rozwiązywało się problem relacji jeden do wielu. Otóż tworzyło się tabelę która zawierała powiązane klucze czyli @IdClass.

Tak to wygląda z perspektywy czasu. Nie wiem czym było podyktowane takie rozwiązania, na pierwszy rzut oka wydają się głupie, może chodziło o szybkość ... i dont know
Jak widać co projekt to inne podejście do problemu...

II Trzeba być bardzo ostrożnym przy ustawianiu id w encji @GeneratedValue. Można ją podłączyć do sesji za pomocą merge(), ale nie można wykonać persist().

Skoro ustawianie id w encji jest bezsensowne to wydaje mi się , że najlepszym rozwiązanie jest udostępnianie konstruktorów które nie przyjmują parametru id i aby go ustawić. Jedynie zostawić odpowiedniego settera dla id. Jeśli ktoś będzie wiedział , że chce zmienić id i wie co robi to ok ma metodę. Czy nie jest to dobre rozwiązanie ?

0

Pytanie o Person i Info - jako ze info zarzadza kluczem, czyli relacja, musisz zadbac aby w info byl ustawiony odpowiedni Person, np. tak jak to zrobiles. Sa tez inne sposoby - np. Person ma metody addInfo, removeInfo (tak, przy usuwaniu musisz zadbac o wyzerowanie referencji do person) itp. Tam, dodajesz Info do kolekcji, oraz ustawiasz Info.setPerson(this) (pseudokod). To jest standard - przeciez chcesz miec spojny graf obiektow - skoro jest to relacja dwukierynkowa, to jak person ma info, to to info musi tez wskazuwac na to person. (Przy wczytywaniu z bazy jpa zadba tak czy tak, ale ty powinienes ten graf miec poprawny rozniez przed zapisem, albo w trakcie jego edycji).
W Info.setPerson byl rowniez wywolal Person.addInfo(this) - tutaj widzisz pewien problem ze dojdzie do cycklu wywolan - ja rozwiazuje to tak ze daje dodatkowe 2 metody ktore maja widocznosc pakietu:

Person:

public addInfo(Info i) { infos.add(i); i.setPersonInternal(this); }
addInfoInternal(Info i) { infos.add(i); }

Info:

public setPerson(Person p) { this.person = p; p.addInfoInternal(this); }
setPersonInternal(Person p) { this.person = p; }

Też tak robię tylko nie mam metod z nazwą Internal...
mam jeszcze metodę w Person:

public void setInfos(List<Info> infos){
	for(Info i : infos){
		i.setClient(this);
	}
	this.orders.addAll(infos);
}

Dodaję te metody ponieważ możliwe jest utworzenie instancji klasy Person używając przykładowo konstruktora bez - argument-owego.
Skoro ty @mućka tak robisz to chyba jest dobrze :)

0

mućka, zamotałeś się z tym hashem i equals oraz Set'ami ;) Pierwsza sprawa, bez problemu da się zaimplementować hash i equals oparte o ID pozwalające normalnie dodawać obiekty do Set'ów. Porównanie dwóch nieutrwalonych obiektów niech zwraca false. I tyle. Innymi słowy, w pseudo-kodzie:

int hashCode() {
    if( id == null ) { return 0; }
    return HASH(id);
}
boolean equals(other) {
    if( other == null || id == null || other.id == null) { return false; }
    return id.equals(other.id)
}

I masz dość czystą sytuację. Owszem - taki HashSet będzie wewnętrznie brzydko zdegenerowany (wszystko poleci do jednego kubełka). Ale działać będzie poprawnie. Z drugiej strony: equals i hashCode porównujący wszystkie pola (albo tylko kilka pól) nie tylko nie pomaga, on potwornie pogarsza sytuację. Każde wywołanie dowolnej metody setXXX na encji zmienia jej hashCode. Więc niemal natychmiast, w czasie zwykłej pracy z encjami, wysadzisz HashSet w powietrze:

// hashcode dla Point na podstawie pól np = x + y;

HashSet points = ...
Point a;
a.x = 2
a.y = 2

points.add(a); // hashcode = 4, obiekt poszedł do kubełka = 4

a.x =666; // hashcode zmienia się na = 668. taki obiekt poszedłby do kubełka 68

points.contains(a); // jest sprawdzana zawartość kubełka 68. tam jest pusto. zwraca FALSE

I mamy schizofrenię, bo z jednej strony contains(a) zwróci false. Z drugiej: iterując po zawartości dostaniesz "a". W Set więc siedzi obiekt widmo. Super. To już lepsza wersja licząca tylko z ID. Tam wywala się tylko w czasie utrwalania. A nie za każdym razem, jak coś się zmienia ;P W zasadzie więc niechcący pokazałeś zupełnie inną zasadę:

złota myśl napisał(a)

bez względu na to, jak napiszesz equals i hashCode, nie jesteś w stanie ich napisać tak, żeby dało się pracować z Set'ami
Do set'ów nie wstawia się obiektów, które zmieniają swój stan. To są pojemniki dobre dla obiektu "immutable"

W zasadzie bez różnicy, jaką strategię wybierzesz:

  1. jeśli uwzględniasz ID: masz błędy związane z utrwalaniem
  2. jeśli uwzględniasz wszystkie pola oprócz ID: masz błędy po wywołaniu jakiegokolwiek settera
  3. jeśli uwzględniasz wybrane pola (czyli wybrałeś tzw natural-id): masz błędy po zmianie tylko tych wybranych pól

Wszystkie rzeczy robi się tak często (zapis, odczyt, modyfikowanie pól), że po prostu nie sposób zagwarantować, że ktoś kiedyś gdzieś się nie pomyli. A błąd jest ekstremalnie trudny do wykrycia. Z natural-id, które jest rozwiązaniem kompromisowym, też są kłopoty: koniec końców ten PESEL albo inny LOGIN też kiedyś trzeba przypisać. Módlmy się, żeby w okolicy w tym czasie nie latał żaden Set, bo jak się komuś coś pomyli... Módlmy się, żeby każdy obiekt, który chcemy trzymać w bazie posiadał pola, które da się jako natural-id traktować... Złą wiadomością jest, że akurat ta modlitwa wysłuchana na pewno nie będzie: istnieją obiekty, które żadnego rozsądnego natural-id nie posiadają. I z pewnością na takie trafimy w swoim życiu.

W jaki sposób więc rozsądnie, niezawodnie i ogólnie rozwiązywać taki problem?

Metoda dla leniwych:

  1. rozwiązać problem utrwalania zgodnie z zaleceniem mućki: hashCode / equals na podstawie innego pola niż primary-key. Primary-key używać tylko w bazie, jako tzw surrogate-key. Określić sobie natural-key.
  2. wbrew przykładom mućki: nigdzie nie używać pojemników Set, a już hash'ujących to wcale ;) Wszystko na List<T> albo Collection<T> ;)

Jeśli zaś Set'ów nie chcemy się pozbywać, albo po prostu chcemy mieć naprawdę ogólne i bezpieczne rozwiązanie, to niestety, ale dużo gorzej:

  1. hashCode / equals na podstawie primary-key
  2. problem z utrwalaniem encji rozwiązać zarządzając primary-key'ami samodzielnie

Co to znaczy: "zarządzać samodzielnie"?
Na pewno zabronić ORM'owi zarządzać ID, bo robi to źle - czyli wywalić @GeneratedValue z adnotacji. Wartość do ID przypisywać już podczas tworzenia obiektu. Setter dla ID walnąć protected. Wypadałoby mieć dodatkowe pole na @Version - żeby biedny Hibernate (albo inny ORM) mógł się jakoś orientować, czy ten obiekt został wczytany z bazy danych. I ponownie: setter dla version zrobić protected. Jak generować primary-key podczas tworzenia: to jest dobre pytanie.

Ogólnie o sprawie z tymi id-kami to sobie kiedyś czytałem w artykule: Don't Let Hibernate Steal Your Identity - i jak sobie wtedy przetrawiłem, tak do tej pory się sprawdza o niebo lepiej, niż cała reszta.

0

Musze przeczytac dokladnie co napisales, troche teraz za pozno, ale moze masz racje.
Jednakze, jest kilka faktow:

  1. niemal kazdy, nawet autogeneratory hibernate, tworza domyslnie hashujace kolekcje
  2. biznesowe dane to dla mnie np. imie i nazwisko, pesel, itp - nie zmienia sie tak predko
  3. jesli liczysz hash zwracajacy 0 dla id null a po zapisaniu zwracasz jakis inny hash to jest to problem duzo wiekszy
  4. nie wiem dlaczego 2 encje niezaposane majace takie same np. pesele czy jakies numery seryjne maja zwrocic false i zapisac sie jako 2 rekordy do bazy danych - jak dla mnie to to nie dziala
  5. do seta wsadzamy juz 'zainicjalizowane' elementy na ktorych juz nie wywolamy zadnego setera - wymaga to minimalna ilosc dyscypliny, ale to podstawa
  6. uzywanie list zamiast setow sprawia, ze use casa z #4 nie da sie uniknac - tam nie ma zadnego sprawdzania duplikatow - ok, powinno sie napisac aplikacje tak zeby takich sytuacji uniknac, doswiadczenie jednak mowi ze to mrzonka
0

A zgadza się jak najbardziej z większością punktów. hashCode i equals zwracający false to raczej sztuka dla sztuki. Po prostu:
"tak się da rozwiązać jakiś jeden konkrenty use-case, ale spowoduje to pewnie inne problemy"

Podobnie cały problem z set'ami sprowadza się do "ostrożności" i "dyscypliny". Po prostu warto takie problemy znać. Chociażby po to, żeby potem sobie nie strzelać w stopy, gdy będziemy pisać kawałki kodu zmieniające ten nieszczęsny PESEL ;)

Właśnie ze względu na mniej więcej takie argumenty, domyślnie rozwiązania oparte są na natural-id (natural-key / domain-key / jak zwał, tak zwał). Bo przy "minimalnej ilosci dyscypliny" da się z tym żyć. Jednak na pewno nie da się żyć z modelem opartym o primary-key, jeśli nie zrobi się czegoś takiego, jak w przytoczonym artcie.

Rozwiązanie omawianie w przytoczonym artykule (tworzenie ID wraz z tworzeniem obiektu, odcięcie ORM'a od zarządzania ID) jest po prostu bardziej skomplikowane - w dodatku utrudnia ręczne grzebanie w bazie danych (128 bitowe klucze główne naprawdę zniechęcają do przeglądania dump'ów ;)). Zysk z rozwiązania jest taki, że naprawdę trudno w takim rozwiązaniu popełnić błąd, niemal się nie da. Nikt nigdy nie napisze złej metody hash/equals - bo nikt jej pisać nie musi. Nikt nie machnie się w Set'ach. Nikt się nie machnie przy wyborze natural-id.

Tzn, że po roku działania systemu nie wyskoczy Ci problem:
"o jasne licho, gość wyrobił nowy dowód, a my nr dowodu używamy w equals'ach"

Przykłady z identyfikatorami dla ludzi są proste - nikt numeru dowodu, imienia albo nazwiska nie będzie brał pod uwagę. Raczej. Chociaż może i tutaj znalazłby projektantów, którzy przy analizie nie wpadną na to, że dowody się gubią, a ludzie biorą śluby i zmieniają im się dane osobowe ;)

Ale realne obiekty potrafią być problemem nawet dla ostrożnych ludzi. Np z fakturami, jeśli chcesz wybrać klucz domenowy, to czeka Cię niezła lektura, żeby mieć pewność, jak ta numeracja faktur się odbywa. I okaże się, że programista, którego poprosiłeś o napisanie prostej encji przyjdzie do Ciebie dopiero po 3 dniach, i stwierdzi: "dobra dobra, potem pogadamy o encji, ja tu się przekwalifikuję na eksperta od prawa podatkowego, a ty mi jakimś Hibernate'm łeb zawracasz" ;) A to nadal jest przykład raczej trywialnego obiektu.

Rozwiązanie jest typu coś-za-coś. Usuwasz sobie sporo problemów przy analizowaniu dziedziny, trochę zwiększasz bezpieczeństwo, do pisania encji możesz zatrudniać stażystów i sekretarki... ;) Ale dzieje się to kosztem komplikacji na poziomie architektonicznym aplikacji (dodatkowa warstwa zarządza UUID dla obiektów). Mnie osobiście to jeszcze nie zawiodło, ale czasem pewnie nie jest to rozwiązanie ani najwygodniejsze, ani nawet zalecane.

0

Nie miałem do czynienia z rozbudowanymi systemami klasy JEE, choćby systemami pisanymi dla klientów z branży finansów. Jednak raczej w takich przypadkach używa się bazy danych Oracle , i stosuje w większości generowanie klucza na podstawie sekwencji.

Ogólnie muszę powiedzieć, że nie jestem zwolennikiem ani JPA , Hibernatea i innych ORM'ów. Ogólnie lepszym rozwiązaniem jeśli chodzi o utrwalanie danych w Javie jest użycie JDO. Jednak z powodów politycznych i finansowych projekt ten nie jest już rozwijany a szkoda. Jest to swoją drogą śmieszna sytuacja kiedy coś co jest lepsze nie jest stosowane a w zamian stosuje się coś co jest bardziej popularne bo stworzone i używane przez firmę XXX.

Jest to przykład jak USB i FireWire , chociaż to drugie było lepsze to i tak wszyscy używali USB. Niestety panowie ale nie zawsze możemy sobie pozwolić na używanie takich metodologi czy też bibliotek i rozwiązań które my uważamy za słuszne zwłaszcza jeśli bierzemy udział w jakimś rozbudowanym projekcie ....

Pisząc dla siebie możemy sobie oczywiście pozwolić na takie rozwiązania.

Na marginesie ciekawe co by powiedzieli @Ranides chciałbym wiedzieć co by powiedzieli projektanci podczas rozpoczęcia projektu nad nową aplikacją gdybyś chciał im przedstawić taki sposób rozwiązania. Ja myślę, że co mądrzejsi by pomyśleli no tak kurcze ma rację, ale zróbmy to panowie jak zawsze wiecie nie ma co wydziwiać. :)

Swoją drogą bardzo ciekawy artykuł i też myślę, że pewne zagadnienia warto znać , dzięki za linka :)

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