19 Eylül 2019 Perşembe

JPA @Inheritance Anotasyonu

Giriş
Şu satırı dahil ederiz.
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
JOINED, SINGLE_TABLE veya TABLE_PER_CLASS olabilir.

- JOINED ile her sınıf kendi tablosuna sahiptir. Ata sınıf ile @PrimaryKeyJoinColumn anotasyonu ile birleşir.
- SINGLE_TABLE'da tüm sınıflar tek tabloda saklanır.
- TABLE_PER_CLASS kullanılmamalı deniliyor.

1. strategy JOINED
JPA @Inheritance + InheritanceType.JOINED yazısına taşıdım.

2. strategy SINGLE_TABLE
Bir hiyerarşinin aynı tabloda saklanması durumunda kullanılır. Açıklaması şöyle.
This table would include columns for all attributes of all classes. An additional column, called the discriminator column, tells Hibernate which type each row corresponds to. The advantage is performance since no joins or unions are needed and polymorphism is therefore fast at the level of the DB. The major disadvantage is that subclasses cannot have fields that are nullable=false, since the columns of these fields are also shared by other subclasses that do not have these fields. This leaves the responsibility of enforcing the data integrity to the programmer, using data validation logic in the business code.
Ata sınıfta @DiscriminatorColumn ile tipleri ayırt etmek için kullanılacak sütun ismi belirtilir. Kalıtan sınıftaysa @DiscriminatorValue ile tipi ayırt etmek için kullanılacak değer belirtilir. Eğer @DiscrminatorValue kullanılmazsa bu değer üretilir. Açıklaması şöyle
We add the @DiscriminatorValue notation to distinguish each entity. If we do not add it, Hibernate uses the entity name as a distinguishing value by default.
Örnek
Ata sınıfta şöyle yaparız.
@Entity
@Table(name = "PERSON")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="discriminator",
    discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue(value="P")
public class Person {
 ...
}
Kalıtan sınıflarda ise Discriminator değer tanımlanır. Şöyle yaparız.
@Entity
@Table(name="PERSON")
@DiscriminatorValue("M")
public class Manager extends Person implements Serializable{
  ...
}
Örnek
Ata sınıfı tanımlamak için şöyle yaparız. Sınıf abstract olduğu için @DiscriminatorValue kullanılmıyor.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE",
  discriminatorType=DiscriminatorType.STRING,length=2)
public abstract class Foo implements Serializable {
  ...
}
Örnek
Ata sınıfı ve kalıtan sınıfı tanımlamak için şöyle yaparız.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "PART_TYPE")
@Table(name = "NAME")
public class NamePartEntity implements Comparable<NamePartEntity> {
  // Stuff
}

@Entity
@DiscriminatorValue(value = "GIV")
public class GivenNameEntity extends NamePartEntity {
  // stuff
}
Kalıtan sınıf için şu sql üretilir.
select this_.person_id as y0_ from name this_ where this_.part_type='GIV'
Örnek
Ata sınıfı tanımlamak için şöyle yaparız.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TYPE", length = 1,
   discriminatorType = DiscriminatorType.STRING)
public abstract class Media {
  ...
}
Kalıtan sınıfı tanımlamak için şöyle yaparız.
@Entity
@DiscriminatorValue("N")
public class NewsReport extends Media {
  ...
}
3. strategy TABLE_PER_CLASS 
Açıklaması şöyle. Ata ve kalıtan sınıflar birbirlerine foreign key ile bağlanmaz. Bu yüzden polymorphic sorgularda UNION ALL yapılmak zorunda kalınır. Yani veri normalizasyona tabi tutulmaz.
Hibernate would use UNION to run polymorphic queries
Örnek
Şöyle yaparız
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Devices {
@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    
    @Column(name="brand")
    private String brand;
    @Column(name="name")
    private String name;
    @Column(name="os")
    private String oS;
}

@Entity
public class Computer extends Devices {
   private String color;
}
Açıklaması şöyle. Yani veri normalizasyona tabi tutulmaz.
In database, "Computer" table has : ID, brand, name, os, color
Örnek
Title alanına göre tüm Publication'ları çekmek isteseydik SQL şöyle olur. Burada okumayı kolaylaştırmak için sadece id alanını bıraktım. Diğer alanları sildim.
select publicatio0_.id as id1_4_, ...
from ( select id ...
       from Book
       union all
       select id ...
       from Magazine ) publicatio0_
where publicatio0_.title=?

Hiç yorum yok:

Yorum Gönder