Kalıtım Stratejileri — Üç Ödeme Türü, Kaç Tablo?
Önce şunu oku: Flush ve SQL Sırası — save() Satırında Neden Hiçbir Şey Olmuyor?
30 saniyede özet
Java'daki bir sınıf ağacını tabloya dökmenin dört yolu var: tek tablo, ortak tablo ve ekler, türe göre ayrı tablo, ya da yalnızca ortak alanları paylaşmak. Her biri bir soruyu ucuzlatır, bir başkasını pahalılaştırır.
Bankada üç tür ödeme var: kartla, havaleyle ve fatura ödemesi. Hepsinin bir tutarı ve bir sahibi var, ama her birinin kendine ait birkaç bilgisi de var. Bunları nasıl dosyalarsın?
-
Bayt: Kodda çok kolay: Payment üst sınıf, altında üç tür. Bitti.
-
Sen: Veritabanında da öyle mi?
-
Bayt: Tablolarda üst sınıf diye bir şey yok ki!
-
Bayt: O zaman bir karar vermemiz gerekiyor. Hangi soruyu daha sık soracağız?
Java’da kalıtım var, tabloda yok
Java’da kalıtımBir sınıfın başka bir sınıfı extends ile genişletip onun API'sini ve uygulamasını devralması. "B, bir A'dır" ilişkisini ifade eder.Sözlükte gör → sayesinde CardPayment bir Payment’tır. Bir listede üç türü karışık tutabilir, hepsine Payment diye bakabilirsin.
İlişkisel tabloların böyle bir kavramı yok. @Inheritance(strategy = …) ile Hibernate’e sınıf ağacını tablolara nasıl dökeceğini söylersin.
Kafam karıştı, daha basit anlat
Kodda bir aile ağacı var, veritabanında yalnızca tablolar. Strateji, aileyi tablolara nasıl yerleştireceğini seçmektir.
@Inheritance anotasyonu Hibernate'e neyi söyler?
@Inheritance yazıp strateji belirtmezsen Hibernate hangisini kullanır?
Üç dolap düzeni
JOINED stratejisi, Payment'ın üç alt sınıfı var. Müşterinin bütün ödemelerini listeleyen sorguda kaç JOIN olur? Cevabı göster
Üç. Ortak bilgiler payments tablosunda, türe özel bilgiler her alt sınıfın kendi tablosunda. Satırın türünü bilmeden okuyacağın için hepsiyle LEFT JOIN yapılır.
Adım adım oku
- SINGLE_TABLE: her şey tek çekmecede, her formda başka türlerin boş kutucukları var.
- JOINED: ortak bilgi bir dosyada, türe özel bilgi zımbalı bir ekte; okurken birleştirilir.
- TABLE_PER_CLASS: her türe ayrı dolap; hepsini görmek için bütün dolapları gezersin.
- Hangisi doğru? En sık sorduğun soruyu ucuzlatan.
SINGLE_TABLE varsayılandır. Bütün türler tek tabloda; satırın türünü bir discriminatorTek tablodaki bir satırın hangi alt sınıfa ait olduğunu söyleyen kolon. Varsayılan değer entity adıdır; @DiscriminatorValue ile sabitlenir.Sözlükte gör → kolonu söyler. Okuma hızlıdır ama kart satırında havale kolonları boş kalır.
JOINED ortak kolonları bir tabloda, türe özel kolonları ayrı tablolarda tutar. TABLE_PER_CLASS her türe bütün kolonlarıyla ayrı bir tablo verir.
Kafam karıştı, daha basit anlat
Tek tablo: hızlı ama boşluklu. JOINED: düzenli ama birleştirmeli. Türe göre tablo: tek türe hızlı, hepsine yavaş.
SINGLE_TABLE'da kart satırının iban kolonu neden boştur?
JOINED stratejisinde bir CardPayment kaydedildi. Kaç INSERT çalışır?
Hangisini seçmeli?
Çoğu sorgu bütün türlere birlikte bakıyorsa ve alt sınıflar birkaç kolon ekliyorsa, SINGLE_TABLE iyi bir başlangıçtır. Türler çok farklıysa ve kısıtlar önemliyse JOINED daha temizdir.
Ortak alanları yalnızca tekrar yazmamak istiyorsan, örneğin id ve createdAt, kalıtım stratejisine gerek yok. @MappedSuperclassOrtak alanları alt entity'lere kopyalayan, kendisi entity olmayan üst sınıf. Tablosu yoktur; ona ilişki kurulamaz ve üzerinden sorgu yazılamaz.Sözlükte gör → bu alanları alt sınıflara kopyalar. Ama üst sınıf veritabanında yoktur.
Kafam karıştı, daha basit anlat
En sık soracağın soruyu düşün ve onu ucuzlatan düzeni seç. Yalnızca birkaç ortak alan paylaşıyorsan @MappedSuperclass yeter.
Yalnızca id ve createdAt alanlarını her entity'de tekrar yazmamak istiyorsun. Hangisi uygun?
Kendin gör
Aynı sınıflar, dört tablo düzeni
Tohum 942428Oynat ya da adımla.
Şu an ne oldu?
JOINED · Müşterinin bütün ödemeleri
Java tarafı hep aynı: Payment ve üç alt sınıfı. Değişen yalnızca tabloların düzeni.
Görevler0/3
Bütün ödemeleri tek tablodan, JOIN'siz okuaçık
İpucu
Hangi stratejide her şey aynı yerde?
Bütün ödemeler için bir UNION ALL ürettiraçık
İpucu
Ortak tablo olmayan ama polimorfik sorgulanabilen strateji.
Kart ödemesini iki satırla kaydet; card_last4 NOT NULL kalabilsinaçık
İpucu
Ortak tablo ve alt tablo.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
- Varsayılanla oynat. JOINED’da bütün ödemeler için üç LEFT JOIN.
- Stratejiyi SINGLE_TABLE yap. Aynı liste tek tablodan, JOIN’siz geldi.
- İşi “kart ödemesi kaydet” yap. Havale ve fatura kolonları NULL gitti.
- TABLE_PER_CLASS’ta listeyi dene. UNION ALL çıktı.
- @MappedSuperclass’ta listeyi dene. Ortak sorgu yok, her tabloya ayrı gidildi.
TABLE_PER_CLASS stratejisinde müşterinin bütün ödemelerini listeleyen sorgu neye dönüşür?
Tuzaklar
Tek tabloda NOT NULL. SINGLE_TABLE’da card_last4 NOT NULL olamaz, çünkü havale satırında boştur. Kuralı uygulama tarafında ya da bir CHECK kısıtıyla korursun.
TABLE_PER_CLASS’ta IDENTITY. Id’ler bütün tablolar boyunca benzersiz olmalı. Her tablonun kendi sayacı bunu garanti edemez; bir sequence kullan.
Discriminator değerini değiştirmek. Varsayılan değer sınıfın adıdır. Sınıfı yeniden adlandırırsan eski satırlar okunamaz; değeri @DiscriminatorValue ile sabitle.
Kafam karıştı, daha basit anlat
Tek tabloda boş kolon kuralını kendin koru, ayrı tablolarda sequence kullan, tür etiketini sınıf adına bırakma.
TABLE_PER_CLASS kullanan bir hiyerarşide id üretimi için IDENTITY neden uygun değildir?
Aşağıdaki örnek bir bankanın ödeme modülünden. Ödemeler tek tabloda, tür etiketi sabit ve boş kalabilen kolonlar bir CHECK ile korunuyor.
Derinleş · Ödemeler: SINGLE_TABLE, sabit etiketler ve korunan kolonlar 6 dosya · ~111 satır · ilk okumada atlayabilirsin
Kendini sına
SINGLE_TABLE, Hibernate'in varsayılan kalıtım stratejisidir.
SINGLE_TABLE'da @DiscriminatorValue yazılmamış. CardPayment sınıfı CardTransaction olarak yeniden adlandırıldı. Ne olur?
Aklında kalacak üç şey
- 1 SINGLE_TABLE bütün türleri tek tabloda tutar: okuma JOIN'siz ve hızlıdır, ama alt sınıf kolonları NOT NULL olamaz.
- 2 JOINED her alt sınıfa kendi tablosunu verir: şema temizdir, ama bütün türlere bakan sorgu her alt tabloyla birleşir. TABLE_PER_CLASS'ta aynı sorgu UNION ALL olur.
- 3 @MappedSuperclass yalnızca ortak alanları paylaşır. Üst sınıf bir entity değildir; ona ilişki kurulamaz ve onun üstünden sorgu yazılamaz.
4 kart sonraki derste seni bekliyor