February 22, 2014

ORM : Inheritance Strategy

Inheritance အား အသုံးပြုခြင်းအားဖြင့် Object တစ်ခုသည် Inheritance လုပ်ထားသော Super Class အမျိုးအစားဖြစ်သည်ဟူသော Is A Relation ကဲ့သို့ ဒေါင်လိုက် ပတ်သက်မှု့အား ဖော်ပြနိုင်၏။

တဘက် Relational Database မှာမူ ဒေတာများအား Table များအတွင်းရှိ Rows များအနေနဲ့ သိမ်းဆည်းထားပြီး၊ ပတ်သက်ပုံအား ဖော်ပြရာတွင် Foreign Key နှင့် Join Table များကိုသာ အသုံးပြုနိုင်၍၊ ၎င်းတို့မှာ အလျားလိုက် ပတ်သက်မှု့ကိုသာ ဖော်ပြနိုင်ပြီး ဒေါင်လိုက်ပတ်သက်မှု့အား ဖော်ပြနိုင်ခြင်းမရှိပေ။

JPA တွင် Inheritance လုပ်ထားသော Entity များအား Relational Database နှင့် @Inheritance Annotation အား အသုံးပြု၍ Map လုပ်ပေးနိုင်ပါသည်။ Java ၏ ဒေါင်လိုက်ပတ်သက်မှု့အား Relational Databases ၏ အလျားလိုက်ပတ်သက်မှု့နှင့် Map လုပ်ရာတွင် Strategy သုံးမျိုးဖြင့် ရွေးချယ် Map လုပ်နိုင်ပါသည်။

  • Single Table Per Class Hierarchy Strategy
    Entity Class Hierarchy တစ်ခုလုံးအား Table တစ်ခုနှင့် Map လုပ်ပေးနိုင်ပါသည်။
  • Joined Subclasses Strategy
    Super Class အား Sub Classes များနှင့် Join လုပ်၍ Map လုပ်ပေးနိုင်ပါသည်။
  • Table Per Concrete Class Strategy
    Concrete Class တစ်ခုစီအား Table တစ်ခုစီနှင့် Map လုပ်ပေးနိုင်ပါသည်။

နမှုနာ အနေနဲ့ အောက်ပါ Entity များအား Strategy အမျိုးမျိုးပြောင်း၍ စမ်းသပ်ကြည့်ပါမည်။




Single Table Per Class Hierarchy Strategy


အကယ်၍ Entity Class တစ်ခုတွင် @Inheritance Annotation အား ရေးသားထား၍၊ အထက်ပါ Strategy အား အသုံးပြုထားပါက အဆိုပါ Class ၏ Subclass များအားလုံးသည် Table တစ်ခုအဖြစ် Map လုပ်ပေးမည် ဖြစ်ပါသည်။ ဤနည်းဖြင့် Map လုပ်ထားသော Table တွင် ပါဝင်သော Data များအား ခွဲခြားသတ်မှတ်ရန် Discriminator Column တစ်ခုအား ပိုင်ဆိုင်ပြီး၊ အဆိုပါ Column အတွင်းရှိ တန်ဖိုးဖြင့် Data များအား ခွဲခြားသတ်မှတ်ပေးနိုင်ပါသည်။

ဤ Strategy အား အသုံးပြုခြင်းအားဖြင့် Class အုပ်စုအတွင်းရှိ Entity များနှင့် Query များအား Polymorphic Relationship အား ဆောင်ရွက်နိုင်ရန် ပံ့ပိုးပေးနိုင်ပါသည်။ သတိပြုရန် အချက်တစ်ခုမှာ Subclass များ၏ State အား ဖော်ပြနေသော Column များအား nullable အဖြစ် ထားရှိရန် လိုအပ်သည် ဆိုသည့် အချက်ပင် ဖြစ်၏။
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Account implements Serializable {
       
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;
    private String name;
    private String password;
    private long major;
    
    // constructors, serial number, getter and setter
}

@Entity
public class Student extends Account implements Serializable {

    private int year;

    // constructors, serial number, getter and setter
}
    
@Entity
public class Teacher extends Account implements Serializable {
    
    private String post;

    // constructors, serial number, getter and setter
}

အထက်ဖော်ပြပါ နမှုနာတွင် Super Class ဖြစ်သော Account Class တွင် @Inheritance Annotation အား အသုံးပြု၍၊ strategy attribute ၏ တန်ဖိုးတွင် InheritanceType.SINGLE_TABLE ဟု ရေးသားထားပါသည်။

ဤနည်းအားဖြင့် Account Entity နှင့် ၎င်း၏ အောက်ရှိ Subclass များအားလုံးအား၊ Table တစ်ခု အနေနှင့် ချိတ်ဆက်ပေးနိုင်မည် ဖြစ်ပါသည်။

အထက်ပါ Entity ဖြင့် Database အား Generate လုပ်ကြည့်သောအခါ အောက်ပါအတိုင်း အဖြေရရှိပါသည်။


အထက်ပါ ပုံတွင်ပါရှိသကဲ့သို့ Superclass ဖြစ်သော Address နှင့် အခြားသော Subclass များဖြစ်ကြသည့် Student နှင့် Teacher Class အားလုံးမှ Properties များသည် Table တစ်ခု အတွင်းသို့ ဝင်ရောက် တည်ဆောက်နေသည် ကိုတွေ့ရပါသည်။ ထို့အပြင် Entity အသီးသီးအား ခွဲခြားနိုင်ရန် DTYPE Column အား တည်ဆောက်၍ သက်ဆိုင်ရာ Entity Name အား တန်ဖိုးအဖြစ် သိမ်းဆည်းပေး နေသည်ကို တွေ့ရပါသည်။

အကယ်၍ DTYPE Column Name နှင့် ၎င်း၏ တန်ဖိုးများအား Customize လုပ်လိုပါက၊ @DiscriminatorColumn နှင့် @DiscriminatorValue တို့အား အသုံးပြု၍ သတ်မှတ်နိုင်ပါသည်။


Joined Subclasses Strategy


Joind Subclasses Strategy အား အသုံးပြုလိုပါက၊ @Inheritance Annotation ၏ strategy attribute တွင် InheritanceType.JOINED ဟု သတ်မှတ်ရေးသားပေးရပါမည်။ Super Class အဖြစ်အသုံးပြုမည့် Table နှင့် အခြားသော Sub Class များအား one to many ဖြင့် Join လုပ်ကာ ချိတ်ဆက်ပေးမည် ဖြစ်ပါသည်။ ဤကဲ့သို့ Joined Subclasses Strategy အား DTYPE Column အား Super Class မှတဆင့် တည်ဆောက်ထားသော Table ထဲတွင် တည်ဆောက်သွားသည်ကို တွေ့ရပါသည်။




Table Per Concrete Class Strategy


Table Per Concrete Class Strategy အား အသုံးပြုလိုပါက၊ @Inheritance Annotation ရဲ့ strategy attribute ရဲ့တန်ဖိုးအား TABLE_PER_CLASS ဟု သတ်မှတ်ရေးသားပေးရပါမည်။ ဤကဲ့သို့ ရေးသားထားခြင်းအားဖြင့် Entity တစ်ခုစီအား သီးခြား Table တစ်ခုစီအနေနှင့် Mapping လုပ်ပေးနိုင်မည် ဖြစ်ပါသည်။ Table တစ်ခုနှင့် တစ်ခုမှာ အချိတ်အဆက်မရှိသောကြောင့်၊ DTYPE Column အား တည်ဆောက်သွားမည် မဟုတ်ပေ။


အထက်ဖော်ပြပါကဲ့သို့ Entity များအား Inheritance လုပ်သည့် အခါမျိုးတွင် သင့်တော်သလို Join Strategy များအား ရွေးချယ်အသုံးပြုသွားနိုင်ပါသည်။



စကားပို


ဤအခန်းကို ရေးမည်ဟု စဉ်းစားထားခဲ့သည်မှာ ကြာပြီဖြစ်သည်။ သို့ရာတွင် ကြားထဲမှာ Java SE အကြောင်း ပြန်လည်ရေးသားနေပါသောကြောင့် ဆက်ရေးချင်ပါသော်လည်း ခေတ္တရပ်ထားခဲ့ရပါသည်။ ဒီအခန်းပြီးလျှင် JPA ၏ အခြေခံ အကြောင်းများနှင့် ORM အကြောင်းကို ပြီးဆုံးမည်ဖြစ်သည်။

သို့ပါသော်လည်း JPA အကြောင်းအား ရေးသားစရာ ကျန်ပါသေးသည်။ Entity Manager အကြောင်း၊ Query အကြောင်းနှင့် Lifecycle အပေါ်မှုတည်ပြီး၊ Listener တွေ၊ Cash အကြောင်းတွေကို ရေးသားရပါဦးမည်။ နောက်အခန်းများအား  အခြားသော Label များနှင့် ဆက်လက်ရေးသားသွားပါဦးမည်။

ဆက်ပါဦးမည်။ လေးစားစွာဖြင့်။
မင်းလွင်

No comments:

Post a Comment