6 Aralık 2023 Çarşamba

JPA @OneToOne Bidirectional İlişki

Giriş
OneToOne ilişki tek veya çift yönlü olabilir. Açıklaması şöyle.
For this relationship type, the default data loading method is EAGER: every time you ask for A, the B will also be retrieved.
Bu ilişki EAGER. Açıklaması şöyle
OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER
Bidirectional İlişki iki şekilde olabilir.
1. Primary key ve foreign key farklı sütunlar
2. Primary key ve foreign key aynı

İlişkinim çift taraflı olması için Parent tarafa mutlaka zaten mappedBy yazmak gerekiyor. Şeklen şöyle


1. Primary key ve foreign key farklı sütunlar
Child üzerinde @JoinColumn kullanır. Şeklen şöyle. Burada her iki sütun için de indeks gerekiyor


Örnek
Şöyle yaparız. mappedBy ile diğer sınıftaki alanı veriyoruz.
@Entity
@Table(name = "PERSON")
public class Person {
  @OneToOne(mappedBy = "person", cascade = CascadeType.ALL)
  private DrivingLicense drivingLicense;
}

@Entity
@Table(name = "DRIVING_LICENSE")
public class DrivingLicense {
  @OneToOne
  @JoinColumn(name = "PERSON_ID", unique = true)
  private Person person;
}
2. Primary key ve foreign key aynı
Child tarafta @PrimaryKeyJoinColumn kullanılır. Şeklen şöyle.


Örnek
Burada @PrimaryKeyJoinColumn ile her iki sınıfın da aynı Id değerine sahip olması sağlanıyor. Parent tarafında şöyle yaparız
@Entity
public class Employee {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;
  ...
  @OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
  private ParkingSpace parkingSpace;
}
Child tarafında şöyle yaparız
@Entity
public class ParkingSpace {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;
   ...
  @OneToOne
  @PrimaryKeyJoinColumn
  private Employee employee;
}
orphanRemoval = true
Yukarıdaki örnekte Person nesnesinin DrivingLicense alanı null yapılırsa DrivingLicense nesnesi de silinir.

cascade Alanı
1. CascadeType.ALL Değeri
CascadeType.ALL eğer Person nesnesi silinirse ona bağlı olan DrivingLicense nesnesinin de otomatik olarak silinmesini sağlar. Ancak orphanRemoval'dan biraz farklıdır. orphanRemoval ile drivingLicense alanını null yapsak bile ehliyet nesnesinin silinmesi sağlanır. 

CascadeType.ALL ile drivingLicense alanını null yaparsak aradaki bağı biz koparttığımız için DrivingLicense nesnesi veri tabanında kalır yani silinmez.


Not : Eğer session.delete(entity); yaparsak DrivingLicense nesnesini silmeye çalışırsak  "org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)" hatasını alırız.

Bu hatanın sebebi OneToOne olan bir ilişkinin tek tarafını kırmaya çalışmamızdan kaynaklanıyor.

Çözüm olarak OneToMany ilişki kullanılması yeterli.

fetchType Alanı
Lazy ise Hibernate 2 sorgu çalıştırır. Şeklen şöyle


optional Alanı
Açıklaması şöyle. Bu alanı false yapabiliyorsak yapmak lazım.
When a @OneToOne or a @ManyToOne relationship is mandatory - that is, the entity must have its associated relationship - it is important to tell JPA that this relationship is not optional.
...
Adding optional = false information will allow JPA to be more efficient in creating its select queries because it will know that it necessarily has an address associated with a person. Therefore, it is good practice to always specify this attribute when defining mandatory relationships.

Hiç yorum yok:

Yorum Gönder