15 Ocak 2019 Salı

JPA OneToOne İlişki

OneToOne İlişki
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.
Unidirectional İlişki
Örnek
Şöyle tanımlarız.
@Entity
@Table(name = Membership_Profile)
class MembershipProfile {
   Long moduleMembershipId;
   String displayName;
   // Other properties if needed
}
ve
@Entity
class PokerProfile {
   @OneToOne(fetch=FetchType.LAZY)
   @JoinColumn(name = "membershipId")
   MembershipProfile membershipProfile;
   ...
}
PokerProfile nesnesi JoinColumn ile hangi membership profile nesnesini ile ilişkili olduğunu bilir.

Örnek
ForeignKeyvermek için şöyle yaparız.
@Entity
public class MediaAnalysis {

  @OneToOne
  @JoinColumn(
    name = "MED_ID",
    nullable = false,
    foreignKey = @ForeignKey(name="MEA_MED_FK")
  )
  private Media media;
  ...

}

Bidirectional İlişki
Örnek'te bir kişi ve ehliyeti var. Yine 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;
}
OneToOne İlişki ve 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 veritabanı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.

mappedBy Alanı
Açıklaması şöyle. Eğer unidirectional ilişki varsa önce kaydedilmesini istediğimiz sınıfa yazarız.
Optional) The field that owns the relationship. This element is only specified on the inverse (non-owning) side of the association.
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