Bir ORM eşlemesinde "sahiplik tarafı" nedir?


129

Sahibi olan taraf tam olarak ne anlama geliyor? Bazı haritalama örneklerinin açıklaması nedir ( birden çoka, bire bir, çoktan bire )?

Aşağıdaki metin, Java EE 6 belgelerinde @OneToOne açıklamasından bir alıntıdır . Konseptin sahip olduğu tarafı görebilirsiniz .

Bire bir çokluğu olan başka bir varlıkla tek değerli bir ilişkilendirmeyi tanımlar. İlişkili hedef varlığın açıkça belirtilmesi normalde gerekli değildir, çünkü genellikle başvurulan nesnenin türünden çıkarılabilir. İlişki çift yönlü ise, sahip olmayan tarafın , sahip tarafın ilişki alanını veya özelliğini belirtmek için OneToOne ek açıklamasının mappedBy öğesini kullanması gerekir.



5
Bunu okuyana
darga33

2
Yabancı anahtar sütununa sahip DB tablosu, sahip taraf olarak kabul edilir. Dolayısıyla, bu DB tablosunu temsil eden işletme, bu ilişkinin Sahibi (Sahiplik tarafı) 'dır. Zorunlu değil, ancak Sahiplik tarafındaki vakaların çoğunda @JoinColumn ek açıklaması olacaktır.
Diablo

Yanıtlar:


202

Sahibi olan taraf kavramı neden gereklidir:

İki yönlü bir ilişkinin sahip olduğu taraf fikri, ilişkisel veritabanlarında nesnelerdeki gibi çift yönlü ilişkiler olmadığı gerçeğinden gelir. Veritabanlarında sadece tek yönlü ilişkilerimiz var - yabancı anahtarlar.

'Sahiplenme tarafı' adının nedeni nedir?

Hibernate tarafından izlenen ilişkinin sahibi olan taraf, ilişkinin veritabanında yabancı anahtara sahip olan tarafıdır .

Taraf sahibi olma fikrinin çözdüğü sorun nedir?

Eşlenen iki tarafın bir örneğini ele alalım olmadan bir sahibi tarafını ilan:

@Entity
@Table(name="PERSONS")
public class Person {
    @OneToMany
    private List<IdDocument>  idDocuments;
}

@Entity
@Table(name="ID_DOCUMENTS")
public class IdDocument {
    @ManyToOne
    private Person person;
}

OO bakış açısına göre, bu eşleme bir çift yönlü ilişkiyi değil, iki ayrı tek yönlü ilişkiyi tanımlar.

Haritalama sadece tablolar yaratacak PERSONSve ID_DOCUMENTSaynı zamanda üçüncü bir bağlantı tablosu yaratacak PERSONS_ID_DOCUMENTS:

CREATE TABLE PERSONS_ID_DOCUMENTS
(
  persons_id bigint NOT NULL,
  id_documents_id bigint NOT NULL,
  CONSTRAINT fk_persons FOREIGN KEY (persons_id) REFERENCES persons (id),
  CONSTRAINT fk_docs FOREIGN KEY (id_documents_id) REFERENCES id_documents (id),
  CONSTRAINT pk UNIQUE (id_documents_id)
)

Birincil anahtar dikkat pküzerinde ID_DOCUMENTSsadece. Bu durumda Hibernate, ilişkinin her iki tarafını bağımsız olarak izler: İlişkiye bir belge eklerseniz Person.idDocuments, ilişkilendirme tablosuna bir kayıt ekler PERSON_ID_DOCUMENTS.

Öte yandan idDocument.setPerson(person)ararsak, masadaki yabancı anahtar person_id'i değiştiririz ID_DOCUMENTS. Hibernate, iki yönlü bir nesne ilişkisi uygulamak için veritabanında iki tek yönlü (yabancı anahtar) ilişki oluşturuyor.

Tarafa sahip olma kavramı sorunu nasıl çözer:

Çoğu zaman istediğimiz şey sadece masaya ID_DOCUMENTSdoğru bir yabancı anahtar PERSONSve ekstra ilişkilendirme tablosu.

Bunu çözmek için, ilgili değişiklikleri izlemeyi durduracak şekilde Hibernate'i yapılandırmamız gerekir Person.idDocuments. Hazırda bekletme , ilişkinin yalnızca diğer tarafını izlemelidirIdDocument.person ve bunu yapmak için mappedBy ekleriz :

@OneToMany(mappedBy="person")
private List<IdDocument>  idDocuments;

MappedBy ne anlama geliyor?

Gibi bu araçlar bir şey: "ilişkisi bu tarafında değişiklikler zaten vardır eşlenen gerek ekstra tabloda ayrı buradan takip etmek, böylece ilişki IdDocument.person diğer tarafında."

Herhangi bir GOTCHA, sonuç var mı?

Kullanılması mappedBy biz sadece çağırırsanız, person.getDocuments().add(document), yabancı anahtar ID_DOCUMENTSolacak DEĞİL bu ilişkinin sahip olma / izlenen tarafı olmadığı için, yeni dokümana bağlantı!

Belgeyi yeni kişiye bağlamak için, açıkça aramanız gerekir document.setPerson(person), çünkü bu, ilişkinin sahibi olan taraftır .

MappedBy kullanılırken , veri tabanındaki yeni ilişkinin kalıcılığını tetiklemek için sahip olan tarafın ne olduğunu bilmek ve ilişkinin doğru tarafını güncellemek geliştiricinin sorumluluğundadır.


17
Bulduğum en iyi cevap 'mappedBy' + 'inversedBy' Doktrini açıklıyor.
Kurt Zhong

1
Eşleştirmeleri ve konseptin arkasındaki nedeni belirttiğiniz için teşekkür ederiz.
Mohnish

1
Bir şeylerin değişip değişmediğini bilmiyorum, ancak 5.0.9 Hazırda Bekletme'de. Son olarak, eğer "sadece ararsam person.getDocuments().add(document)", yabancı anahtarı içeride günceller ID_DOCUMENTS.
K.Nicholas

1
@Karl Nicholas, merhaba, size katılıyorum, @OneToManyek açıklamada PERSIST olarak ayarlanabilen basamaklı özniteliğimiz var bu durumda hazırda bekletme tüm bağlı varlıkları DB'ye kaydedecektir. Herhangi biri bunu açıklayabilir mi - neden yazar hazırda bekletmenin sahipsiz taraftaki değişiklikleri izlemeyeceğini söylüyor - ama aslında hazırda bekletme izleme gerçekleştiriyor?
Oleksandr Papchenko

3
cascade, sağlayıcıya, ana varlık onlara sahip olmasa bile alt varlıkları kaydetmesini söyler, böylece kuralı etkili bir şekilde değiştirir. MappedBy = child.field varsa (veya varsa) ve basamaklama yapmadıysanız, listenin alt öğeleri kaydedilmeyecektir. Ayrıca, eğer eşleme yapmadıysanız VE basamaklama yapmadıysanız, o zaman Ebeveyn ilişkinin sahibidir ve listeye YENİ çocuklar koyarsanız ve ardından Ebeveyni kaydederseniz, bir istisna atacaktır çünkü yeni çocuk kimlikleri mevcut değildir. katılma tablosuna kaydedilir. Umarım işleri açıklığa kavuşturur ... :)
K.Nicholas

142

Sahibi olan tarafın diğer tarafa referans veren varlık olduğunu hayal edebilirsiniz . Alıntıda bire bir ilişkiniz var. Bir olduğuna göre simetrik ilişki, nesne bir de tersi daha sonra nesne B ile ilgili olarak ise doğruysa o sahip bitireceğiz.

Bu, A nesnesine B nesnesine bir referans kaydetmenin ve B nesnesine A nesnesine bir referans kaydetmenin gereksiz olacağı anlamına gelir: bu nedenle, hangi nesnenin diğerinin kendisine "sahip" olduğunu seçersiniz.

Bire çok bir ilişkiniz olduğunda, "çok" bölümüyle ilgili nesneler sahiplik tarafı olacaktır, aksi takdirde tek bir nesneden çokluğa birçok referansı saklamanız gerekir. Bundan kaçınmak için, ikinci sınıftaki her nesnenin başvurdukları tek nesneye bir işaretçisi olacaktır (bu nedenle onlar sahip olan taraftır).

Çoktan çoğa bir ilişki için, ayrı bir eşleme tablosuna ihtiyacınız olacağından, zaten herhangi bir sahiplik tarafı olmayacaktır.

Sonuç olarak, sahip olan taraf , diğerine referans veren varlıktır.


6
Açıklık getirdiğiniz için teşekkürler.
Sadece bir öğrenci

2
'mappedBy' ve 'ownering side' isimleriyle ilgili nedenlerim için cevabımı aşağıda görmeye yardımcı olabilir, bir sahiplik tarafı, GOTCHA'yı tanımlamazsak ne olur, umarım yardımcı olur
Angular University

5
Sanırım cevap çoğunlukla doğru. Ancak en azından Hazırda Bekletme için çoktan çoğa ilişkilerin bile sahiplenme tarafı vardır. Bu, örneğin güncelleme davranışı için etkilere sahiptir. Bu eğiticinin
Pfiver

11
Bu cevap yardımcı olduğundan daha fazla kafa karıştırıyor. Çift yönlü ilişkilerde her iki Varlık nesnesinin de birbirine referansı olacaksa "Sahip olan tarafın diğer tarafa referans veren varlık olduğunu hayal edebilirsiniz" demenin ne anlamı var? Ayrıca, "Çoktan çoğa bir ilişki için, ayrı bir eşleme tablosuna ihtiyacınız olacağı için zaten sahiplik tarafı olmayacak" düpedüz yanlıştır: @ManyToManyilişkilerin de kendi tarafları vardır. Benzer şekilde, @OneToManyilişkiler birleştirme tablolarını kullanabilir ve yine de bir sahip taraf belirtmeniz gerekir.
Davids

5
Temel olarak, bu olumlu oyları olan sevimli, iyi hissettiren bir cevaptır çünkü anlamak gerçeklerden daha kolaydır.
Davids
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.