Çözüldü Java JPA ve Veritabanı ilişkisi nasıl kurulur?

Bu konu çözüldü olarak işaretlenmiştir. Çözülmediğini düşünüyorsanız konuyu rapor edebilirsiniz.

xgravity

Picopat
Katılım
12 Mayıs 2025
Mesajlar
353
Çözümler
3
Daha fazla  
Cinsiyet
Erkek
Arkadaşlar merhaba. JPA kullanarak veri tabanı modelleme hakkında bir kaç sorum olacaktı. Yardımcı olursanız ve beni aydınlatırsanız çok sevinirim.

1. Sorum; İlişkileri nasıl kurarız?
JPA annotasyonları olan @OneToOne, @OneToMany vb. kullanarak entity sınıflarının (veri tabanı tablolarının) ilişkilerini sağlıyoruz. Şimdi örnek durumlarımın bunlar;

  • Bir account'un bir rolü var.
  • Bir account'un birçok konusu var.

Bunların ilişkileri nasıl belirtilir?

2. Sorum; İlişki sahibinin önemi nedir ve hangi tablonun ilişki sahibi olduğu nasıl belirlenir?
 
Çözüm
@bitwise

Query sorgu oluyor değil mi hocam?
Şimdi tabii ki büyük çaplı bir şey geliştirmiyorum fakat.

Diyelim şöyle sınıf yapısı yaparsak

User {
void ReadTopic()
}

User level atladı Modaretör oldu diyelim

User: Moderator {
void ReadTopic()
void DeleteTopic()
void BanAccount()
}

User baktık çok iyi gidiyor bunu bir de Admin yapalım

User: Modarator, Admin {

void ReadTopic()
void DeleteTopic()
void BanAccount()
void DeleteAccount()
void CreateCategory()


}

gibi Roller, servise katmanında böyle if, else olmadan yetkileri olmalı böyle.

Burada User siniflarina fazla sorumluluk yuklemis oluyorsun. User sadece bir kullaniciyi temsil etmeli; account silmemeli ya da kategori olusturmamali. User in tek yapmasi gereken kendi rolu neyse soruldugunda buna cevap vermeli.

Java:
public interface User {
    Set<Role> getRoles();
}

public class RegisteredUser implements User {
    @Override
    public Set<Role> getRoles() {
        return null;
    }
    // diger seyler
}

public class GuestUser implements User {
    @Override
    public Set<Role> getRoles() {
        return null;
    }
}

Servis katmaninda ise; kullanicinin bu ise yetkisinin olup olmadiginin kontrolunu yapmak da dogru degil. Havaalanindaki guvenlik gibi dusun bunu. Bir yere cizgi cekersin, guvenlik kontrolu koyarsin ve oradan sonraki herkesin silahsiz oldugunu kabul edersin. Iste servis katmani bu guvenli bolgede bulunmali.

Aksi halde tum servislerinde "Bu adamin bu ise yetkisi var mi" kontrolu yapmak zorunda kalirsin ve uygulama spagettiye dogru gider.

Ideal olani, yapilacak islem icin istek yapildiginda bu istegi karsilayan ilk kimse orada direkt guvenlik kontrolunu yapmak ve guvensiz istegi en kisa surede geri yollamak. Bu da Controller ya da onun yerine gececek ( Interceptor, DIspatcher vs ) diger ara katmanlar demek oluyor.

Request geldi sunucuna, kimin istek attigini analiz ettin; yapmak istedigi islemi analiz ettin. Kisiyi temsil eden User her ne ise ( Admin, Moderator vs fark etmez ) ondan sana rolunu soylemesini istedin. Daha sonra buRolunBuIslemeYetkisiVarMi() seklinde bir fonksiyon ile guvenligi sagladin ve gecirdin. Servis tarafinda artik her islem valid demektir guvenlik acisindan.

Servis tarafinda if-else kullanimina bu sekilde gerek kalmaz cunku yetkilendirilmis bir islem oldugunu biliyorsun. deleteAccount(123) seklinde silinmesi gereken account bilgisini almasi yeterli. Islemi kimin yaptigini bilmesine bile gerek yok.

Spring kullaniyorsan UserDetails :: Spring Security bu islem icin yazilmis bir interface.

Kullanmiyorsan Java'nin kendi interface'i Principal i kullanabilirsin ama biraz basit kaliyor. Kendin de yazabilirsin; artik uygulamanin dizaynina gore.

Rol bazli guvenlik sistemleri basit olarak bu problemi cozerler ancak zamanla uygulama kompeks oldukca yetersiz gelir; "Sunu yapsin ama bunu yapamasin" diye dusunerek kendini yeni roller tanimlarken bulursan bil ki hata yapiyorsun. Oradan da Grant ve Authority kavramlarina gecis yaparsin ama onu da baska zaman tartisiriz. Ornegin su sekilde kompleks senaryolar olusabilir, verilen bir siparisle ilgili detaylara cagri merkezi kismi olarak ulasabilsin, siparisin sahibi tamamen ulassin, yoneticiler finansal bilgileri dahil edecek sekilde ulassin; siparisten yeterince zaman gectiyse yalnizca yoneticiler ulassin vs gibi.
Rolun kendisinin de Authority' listesi olacagini varsayarak;

Role ayri bir entity,

Account uzerinde @ManyToOne seklinde tanimlamak en makulu.

---

Account ve Topic iliskisi DB yi nasil dizayn etmek istedigine gore degisir. Burada da Topic uzerinde ManyToOne yapmak en dogali, Account'u referans eden FK Topic uzerinde belirlenmeli.

Eger uygulama katmaninda Account uzerinden topic listesi manipule edilecekse @OneToMany(mapped = ( ya da mappedBy ; hatirlayamadim su anda ) yapabilirsin.

---

"Iliski sahibi" diye bir sey RDBMS nosyonunda yok. ORM'ler hangi tarafa FK constraint i atacagini kestirmek icin bu kavrami ortaya atiyorlar.

Account tarafta @OneToMany(mappedBy = ) yaptigin zatan bu FK'nin Topic tablosunda islenecegini gosterir. FK erisimi olmadigi icin de, account'un topic listesine yeni eleman eklemen DB ye kayit tetiklemeyecek. Dolayisiyla owner Topic olmus oluyor. Ezberci egitimden nefret etsem de, maplenen entity kimse mapleyen taraf relation owner gibi dusunebilirsin.

JPA yi bir kenara birakip DB dizayn ettigini dusun.

AccountTopics seklinde yeni bir tablo olusturup burada hangi account ile hangi topic'in eslestigini tutabilirsin.

Topics tarafinda account_id seklinde foreign key tanimi yaparak tutabilirsin bu veriyi.

Ya da Account tablosunda topic_id seklinde tutabilirsin. Hangisi isine geliyorsa JPA yi bunu yapacak sekilde yonlendiriyorsun. Iliski sahibi de FK kimin kontrolundeyse o oluyor. Aslinda DB de iliski sahibi diye bir sey yok. JPA cascade yonetimi vs icin buna ihtiyac duyuyor.
 
Son düzenleme:
@bitwise, öncelikle account-role hakkinda soru sorayim, eger cevaplamak isterseniz tabii.

Diyelim ki sisteme 5 role kayit ettik. 10 account 1 role'yi isaret edebilir degil mi? Bunda sorun olmaz yani.
 
@bitwise, öncelikle account-role hakkinda soru sorayim, eger cevaplamak isterseniz tabii.

Diyelim ki sisteme 5 role kayit ettik. 10 account 1 role'yi isaret edebilir degil mi? Bunda sorun olmaz yani.

Eger @ManyToOne tanimlandiyse; Role ~ Account arasinda 1-n iliskisi vardir demektir. 10 Account ayni role entity'sine sahip olabilir. Ama 1 Account'un 2 rolu olamaz.

Bu iste genellikle soyle yapilir; ileride @ManyToMany olmasina ihtimal verdigin bir iliski varsa 3. bir tablo acip orada tutarsin. Boylece istersen 1-N isersen N-N iliskiye dondurebilirsin.

Dezavantaji, her rol query'si icin join yapman gerekir ama esnek olur.

Eger her Account icin yalnizca 1 Role olacaksa o halde Role tarafinda foreign key atmak, yani @ManyToOne hem performansli hem de daha az kodla halledilebilir olur.
 
@bitwise
her rol query'si icin join yapman gerekir ama esnek olur.
Query sorgu oluyor değil mi hocam?
Şimdi tabii ki büyük çaplı bir şey geliştirmiyorum fakat.

Diyelim şöyle sınıf yapısı yaparsak

User {
void ReadTopic()
}

User level atladı Modaretör oldu diyelim

User: Moderator {
void ReadTopic()
void DeleteTopic()
void BanAccount()
}

User baktık çok iyi gidiyor bunu bir de Admin yapalım

User: Modarator, Admin {

void ReadTopic()
void DeleteTopic()
void BanAccount()
void DeleteAccount()
void CreateCategory()


}

gibi Roller, servise katmanında böyle if, else olmadan yetkileri olmalı böyle.
 
@bitwise

Query sorgu oluyor değil mi hocam?
Şimdi tabii ki büyük çaplı bir şey geliştirmiyorum fakat.

Diyelim şöyle sınıf yapısı yaparsak

User {
void ReadTopic()
}

User level atladı Modaretör oldu diyelim

User: Moderator {
void ReadTopic()
void DeleteTopic()
void BanAccount()
}

User baktık çok iyi gidiyor bunu bir de Admin yapalım

User: Modarator, Admin {

void ReadTopic()
void DeleteTopic()
void BanAccount()
void DeleteAccount()
void CreateCategory()


}

gibi Roller, servise katmanında böyle if, else olmadan yetkileri olmalı böyle.

Burada User siniflarina fazla sorumluluk yuklemis oluyorsun. User sadece bir kullaniciyi temsil etmeli; account silmemeli ya da kategori olusturmamali. User in tek yapmasi gereken kendi rolu neyse soruldugunda buna cevap vermeli.

Java:
public interface User {
    Set<Role> getRoles();
}

public class RegisteredUser implements User {
    @Override
    public Set<Role> getRoles() {
        return null;
    }
    // diger seyler
}

public class GuestUser implements User {
    @Override
    public Set<Role> getRoles() {
        return null;
    }
}

Servis katmaninda ise; kullanicinin bu ise yetkisinin olup olmadiginin kontrolunu yapmak da dogru degil. Havaalanindaki guvenlik gibi dusun bunu. Bir yere cizgi cekersin, guvenlik kontrolu koyarsin ve oradan sonraki herkesin silahsiz oldugunu kabul edersin. Iste servis katmani bu guvenli bolgede bulunmali.

Aksi halde tum servislerinde "Bu adamin bu ise yetkisi var mi" kontrolu yapmak zorunda kalirsin ve uygulama spagettiye dogru gider.

Ideal olani, yapilacak islem icin istek yapildiginda bu istegi karsilayan ilk kimse orada direkt guvenlik kontrolunu yapmak ve guvensiz istegi en kisa surede geri yollamak. Bu da Controller ya da onun yerine gececek ( Interceptor, DIspatcher vs ) diger ara katmanlar demek oluyor.

Request geldi sunucuna, kimin istek attigini analiz ettin; yapmak istedigi islemi analiz ettin. Kisiyi temsil eden User her ne ise ( Admin, Moderator vs fark etmez ) ondan sana rolunu soylemesini istedin. Daha sonra buRolunBuIslemeYetkisiVarMi() seklinde bir fonksiyon ile guvenligi sagladin ve gecirdin. Servis tarafinda artik her islem valid demektir guvenlik acisindan.

Servis tarafinda if-else kullanimina bu sekilde gerek kalmaz cunku yetkilendirilmis bir islem oldugunu biliyorsun. deleteAccount(123) seklinde silinmesi gereken account bilgisini almasi yeterli. Islemi kimin yaptigini bilmesine bile gerek yok.

Spring kullaniyorsan UserDetails :: Spring Security bu islem icin yazilmis bir interface.

Kullanmiyorsan Java'nin kendi interface'i Principal i kullanabilirsin ama biraz basit kaliyor. Kendin de yazabilirsin; artik uygulamanin dizaynina gore.

Rol bazli guvenlik sistemleri basit olarak bu problemi cozerler ancak zamanla uygulama kompeks oldukca yetersiz gelir; "Sunu yapsin ama bunu yapamasin" diye dusunerek kendini yeni roller tanimlarken bulursan bil ki hata yapiyorsun. Oradan da Grant ve Authority kavramlarina gecis yaparsin ama onu da baska zaman tartisiriz. Ornegin su sekilde kompleks senaryolar olusabilir, verilen bir siparisle ilgili detaylara cagri merkezi kismi olarak ulasabilsin, siparisin sahibi tamamen ulassin, yoneticiler finansal bilgileri dahil edecek sekilde ulassin; siparisten yeterince zaman gectiyse yalnizca yoneticiler ulassin vs gibi.
 
Son düzenleme:
Çözüm
Request geldi sunucuna, kimin istek attigini analiz ettin; yapmak istedigi islemi analiz ettin. Kisiyi temsil eden User her ne ise ( Admin, Moderator vs fark etmez ) ondan sana rolunu soylemesini istedin. Daha sonra buRolunBuIslemeYetkisiVarMi() seklinde bir fonksiyon ile guvenligi sagladin ve gecirdin. Servis
tarafinda artik her islem valid demektir guvenlik acisindan.
Servis tarafinda if-else kullanimina bu sekilde gerek kalmaz cunku yetkilendirilmis bir islem oldugunu biliyorsun. deleteAccount(123) seklinde silinmesi gereken account bilgisini almasi yeterli. Islemi kimin yaptigini bilmesine bile gerek yok.
Aynen şimdi hatırladım.

WebConfig'te ya da Controller'da API üstüne PreAuthorize diye bir annotasyon koyup, "ADMIN" ya da "Modarator" diye belirtiyordun. UserDetail ile user'ın rolü bulunuyordu. Yani if, else yapmıyordun ve direkt servis katmanında hangi işlemi yapmasını istiyorsan yapıyordun.

Yani bir nevi Authentication idi bu.

Rol bazli guvenlik sistemleri basit olarak bu problemi cozerler ancak zamanla uygulama kompeks oldukca yetersiz gelir; "Sunu yapsin ama bunu yapamasin" diye dusunerek kendini yeni roller tanimlarken bulursan bil ki hata yapiyorsun. Oradan da Grant ve Authority kavramlarina gecis yaparsin ama onu da baska zaman tartisiriz. Ornegin su sekilde kompleks senaryolar olusabilir, verilen bir siparisle ilgili detaylara cagri merkezi kismi olarak ulasabilsin, siparisin sahibi tamamen ulassin, yoneticiler finansal bilgileri dahil edecek sekilde ulassin; siparisten yeterince zaman gectiyse yalnizca yoneticiler ulassin vs gibi.
Yani Spring Security, kullanıcıyı analiz etsin, kullanıcı zaten yetkili bir abi ise istenilen API'lere sorunsuzca erişebilir.


Hocam ben oradan buradan yapmıştım bir şeyler fakat bu Document okumayı hiç yapamıyorum. Spring tamam iyi güzel biliyorum birazcık ama Document okuyarak yapamadım hiç. Baeldung sitesinde örnekle anlatıyorlar, ordan öğrenmiştim Springboot'u. Spring'in ne olduğunu da Akın hocanın eğitim seti videosunu izleyerek öğrenmiştim.

Birde öğreniyorum ama bugün bir reklam gördüm. Hostinger diye bir siteye iki-üç komut giriyorsun ve Web sitesi yapıyor hemen. Ondan bazen de boşuna emek veriyorum diye düşünüyorum.
 
Son düzenleme:
WebConfig'te ya da Controller'da API üstüne PreAuthorize diye bir annotasyon koyup,

Evet dogru. Aslinda servis katmanina da konulabilir bu ama ne kadar erken o kadar iyi. "Fail fast" prensibi.

Hocam ben oradan buradan yapmıştım bir şeyler fakat bu Document okumayı hiç yapamıyorum. Spring tamam iyi güzel biliyorum birazcık ama Document okuyarak yapamadım hiç. Baeldung sitesinde örnekle anlatıyorlar, ordan öğrenmiştim Springboot'u. Spring'in ne olduğunu da Akın hocanın eğitim seti videosunu izleyerek öğrenmiştim.

Birde öğreniyorum ama bugün bir reklam gördüm. Hostinger diye bir siteye iki-üç komut giriyorsun ve Web sitesi yapıyor hemen. Ondan bazen de boşuna emek veriyorum diye düşünüyorum.

Ilk baslarda normal ornekler uzerinden ilerlemek normal. Sonrasinda direkt kaynagina inmek ya da spesifikasyonunu okumak gerekiyor. Gidip herhangi bir web sitesinden, ki Baeldung basarili, ornekler takip etmekten cok daha kesin bilgiye hizli sekilde ulasabiliyorsun boylece.

Bu da web projesi yapabilen web projesini birilerinin yapabildigini gosteriyor. Malesef ogrenme asamasinda yazdigimiz kodun ezici cogunlugu cope gidecek ama boyle boyle ogreniliyor; yapacak bir sey yok. Belirli bir sure sonra zaten AI ya da benzeri toollarin uretebileceginden daha yetkin seyler ortaya cikarabileceksin, o zamana kadar azimle ugrasmaya devam.

Amac ogrenmek degil de direkt proje cikarmaksa ama alternatiflere sans vermek iyi. Her projeyi spring security ile kastirmaya hic gerek yok.
 

Technopat Haberler

Yeni konular

Geri
Yukarı