2011-12-20 7 views
7

Mimo że moje pytanie jest sformułowane konkretnie w odniesieniu do sposobu przedstawiania relacji Entity w strukturze Play, która używa Hibernate, jestem pewien, że jest to ogólne pojęcie.Próba zrozumienia znaczenia posiadania jednej z wielu relacji w ORM

Kiedy mamy relację jeden-do-wielu, zawsze jesteśmy proszeni o określenie strony posiadania.

Tak więc, na przykład, gdybyśmy mieli relację jeden do wielu między osobą a numerem telefonu, napisalibyśmy kod taki jak ten.

@Entity 
class Person { 
    @OneToMany(mappedBy="person") 
    public Set<PhoneNumber> phoneNumbers; 
} 

@Entity 
class PhoneNumber { 
    @ManyToOne 
    public Person person; 
} 

W powyższym kodzie podmiot będący właścicielem to PhoneNumber. Jakie są plusy i minusy którejkolwiek ze stron, która jest właścicielem?

Zdaję sobie sprawę, że gdy właścicielem jest PhoneNumber, reprezentowana relacja to ManyToOne, która nie będzie skutkowała połączeniem tabeli, natomiast gdy strona posiadająca jest Person, przedstawiony związek będzie OneToMany, w którym to przypadku tabela relacji będzie bądź kreatywny.

Czy to jest główny powód określenia strony posiadania, czy też istnieją inne powody?

Aktualizacja: zdałem sobie sprawę, że this thread stanowi część odpowiedzi, ale mam nadzieję, że mogą istnieć inne punkty, jak również.

Odpowiedz

1

W przypadku większości warstw ORM masz pojęcie leniwego ładowania. Gdy utworzysz obiekt Person, nie będzie on ładował zestawów telefonów, o ile nie zostanie o to poproszony. Czasami sposób wyszukiwania danych może również określać sposób ich przechowywania.

Np. Jeśli chcesz najpierw przywołać osobę, a następnie wyświetlić numery telefonów na żądanie, to utrzymywanie referencji osoby w telefonie jest w porządku. Najpierw wystrzeliwujesz proste zapytanie, aby załadować dane osobowe, a następnie sprawdzasz numery telefonów na podstawie (już załadowanej) osoby.id (inne proste zapytanie).

Podczas gdy dane osobowe + telefonu są wyświetlane za jednym zamachem, wolisz mieć tabela łączenia, w której można po prostu ładować dane w oparciu o tabelę osób i tabelę dołączania do osób, używając identyfikatora osoby jako klucza do tabeli telefonu, wszystko za jednym razem. Tutaj byłoby drogo robić wyszukiwania bez tabeli relacji.

Ale szczerze mówiąc, jeśli myślisz, że SQL zamiast ORM potem pójdziesz ze stołem związku każdym razem: D

+0

Próbuję myśleć głośno. Powiedzmy, że w obu przypadkach robimy szybkie pobieranie. W pierwszym przypadku, w którym PhoneNumber jest podmiotem będącym właścicielem, uruchomimy pierwsze zapytanie, aby uzyskać wszystkie podmioty Person, a następnie uruchamiamy indywidualne zapytania dla każdej Osoby, aby uzyskać wszystkie Numer telefonu dla tej Osoby. Jednakże, gdybyśmy mieli Osobę jako stronę będącą właścicielem, potrzebujemy odpalić tylko jedno zapytanie z łączeniem. Przykro mi, jeśli jest to głupie pytanie, ale czy dołączenie nie jest możliwe z osobą będącą FK w PhoneNumber? – Parag

+0

Tak, połączenie powinno być możliwe z identyfikatorem osoby FK również w tabeli telefonicznej.Tutaj (zakładając), że znormalizowane wyszukiwanie byłoby szybsze, ale musisz spojrzeć na swój plan wyjaśniający, aby być pewnym. Innym powodem (przynajmniej teoretycznym) do użycia tabeli relacji byłoby umożliwienie udostępniania numerów telefonów, takich jak numer telefonu używany przez dwie osoby na zmiany. Szczerze mówiąc, to, jak działa warstwa ORM, powinno być nieistotne dla takich rozważań, ponieważ nikt nie projektuje schematu z warstwą ORM mając na uwadze – rjha94

+0

zobacz moją odpowiedź w tym wątku oraz przyczyny dla nazw 'mappedBy' i 'owning side', co się dzieje jeśli nie zdefiniujemy strony posiadania, GOTCHAs - http://stackoverflow.com/questions/2749689/what-is-the-owning-side-in-an-orm-mapping/21068644#21068644 –

6

ważnym punktem pamiętać, jest to, że relacja będącym właścicielem jest ten, który faktycznie utrzymują się relacja przy zapisie. Na przykład:

Person person = new Person(); 
    PhoneNumber pn = new PhoneNumber(); 
    pn.phone = "12345678"; 
    person.phoneNumbers.add(pn); 
    session.save(person); 

Relacja nie jest zapisana w rzeczywistości, jeśli przeładujesz encję z bazy danych, nie zobaczysz żadnych liczb. Aby dodać relację, musisz ustawić osobę po stronie właściciela (PhoneNumber), a następnie zapisać.

// the relation is not saved 
    Person loadedPerson = (Person)session.load(Person.class, person.id); 
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 0! 

    pn.person = person; 
    session.save(pn); 

    loadedPerson = (Person)session.load(Person.class, person.id); 
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 1