January 9, 2014

ORM : Primary Key Columns

Relational Database များတွင် Data များအား Row များအနေဖြင့် Table များတွင် သိမ်းဆည်း လေ့ရှိပါသည်။ Table အတွင်းရှိ Row များအား Identified ပြုလုပ်ရန် အတွက် Primary Key Constraint အား အသုံးပြု၍ သတ်မှတ်ပါသည်။ Primary Key Columns များအတွင်း တန်ဖိုးတစ်ခုအား နှစ်ခါထည့်၍မရပေ။ Primary Key Column အတွင်းရှိ တန်ဖိုးဖြင့် Table အတွင်းရှိ Row များအား ခွဲခြားသတ်မှတ်ရန် လိုအပ်သောကြောင့် ဖြစ်ပါသည်။

JPA တွင် Relational Database အတွင်းရှိ Table များအား POJO Class ဖြစ်သော Entity နှင့် Mapping လုပ်ထားပြီး၊ Primary Key Column နှင့် @Id Annotation အား ရေးသားထားသော Fields များအား Map လုပ်ထားပါသည်။ Relational Database ၏ Table တစ်ခုတွင် Primary Key သည် မရှိမဖြစ်လိုအပ်သကဲ့သို့ပင် Entity Class တွင်လည်း Id Field သည်လည်း မရှိမဖြစ်လိုအပ်ပါသည်။


Primary Key Column


Primary Key Column များအား Entity Class နှင့် Mapping လုပ်ရန်အတွက် @Id Annotation အား အသုံးပြုရပါသည်။ အသုံးပြုနိုင်သော Java Type များမှာ အောက်ပါအတိုင်း ဖြစ်ပါသည်။

  • Primitive Type : byte, int, short, long and char
  • Wrapper Class : Byte, Integer, Integer, Short, Long and Character
  • Array of Primitive and Wrapper Types : int [] , Integer []
  • String , BigInteger and Date

Entity Class များအား ရေးသားရာတွင် ID Fields များ၏ တန်ဖိုးများအား Application များမှတဆင့် Manual အနေနဲ့ ဖြည့်စွက်ပေးနိုင်သလို API မှလည်း အလိုအလျှောက် ဖြည့်စွက်ပေးနိုင်ပါသည်။ အလိုအလျှောက် ဖြည့်စွက်ရန်မှာ @GenerateValue Annotation အား အသုံးပြုရန် လိုအပ်၏။ အသုံးပြုနိုင်သော တန်ဖိုးများမှာ အောက်ပါအတိုင်း ဖြစ်ပါသည်။
  • SEQUENCE နှင့် IDENTITY သည် Database ၏ Sequence Object ဒါမှမဟုတ် Identity များအား အသီးသီး သတ်မှတ်ပေးနိုင်ပါသည်။
  • TABLE Strategy အား အသုံးပြုထားပါက Sequence Table အား Database အတွင်းတွင် တည်ဆောက်၍ အသုံးပြုသွားမည် ဖြစ်ပါသည်။
  • AUTO အား အသုံးပြုပါက JPA Engine မှနေ၍ TABLE ဒါမှမဟုတ် SEQUENCE တို့အား သင့်တော်သလို ရွေးချယ်၍ အသုံးပြုသွားမည် ဖြစ်၏။ တဖန် GenerateValue အား ရေးသားထားသော်လည်း တန်ဖိုးအား ဖြည့်စွက်ထားခြင်း မရှိပါက Default အနေနှင့် AUTO အား အသုံးပြုမည် ဖြစ်ပါသည်။

IDENTITY Strategy အား အသုံးပြုခြင်း


IDENTITY Strategy အား Auto Increment အသုံးပြုနိုင်သော MySQL  ကဲ့သို့ DBMS များတွင် အသုံးပြုနိုင်ပါသည်။ GenerateValue ၏ strategy တွင် IDENTITY  အဖြစ်ရေးသား ထားပါက Auto Increment အဖြစ် အသုံးပြုနိုင်မည် ဖြစ်သည်။ Entity မှ တဆင့် Table အား Create လုပ်ပါက IDENTITY အဖြစ်သတ်မှတ်ထားသော ID Column များအား Auto Increment အဖြစ် Create လုပ်မည် ဖြစ်ပါသည်။

အကယ်၍ Auto Increment Key Column များရှိပါက IDENTITY Strategy အဖြစ် အသုံးပြုရမည် ဖြစ်သည်။ IDENTITY Strategy မှာ ယခင် အခန်းများတွင်လည်း ဖော်ပြပြီး ဖြစ်သောကြောင့် ဤ နေရာတွင် အထွေအထူး ဖော်ပြတော့မည် မဟုတ်ပါ။


AUTO Strategy အား အသုံးပြုခြင်း

နမှုနာ အနေဖြင့် AUTO Strategy အား အသုံးပြုကြည့်ပါမည်။ အသုံးပြုမည့် Database မှာ Derby Embedded ပတ်ဝင်းကျင် ဖြစ်ပါသည်။ Derby သည် JDK တွင်ပါဝင်ပြီး ဖြစ်သောကြောင့် အထွေအထူး Database အား Installed လုပ်စရာမလိုပဲ အသုံးပြု နိုင်မည်ဖြစ်ပါသည်။ ထို့အပြင် တော်ရုံ Desktop Application အား အသုံးပြုပါက Derby အား အသုံးပြုရသည်မှာ အစဉ်ပြေလှပါသည်။ ဥပမာအားဖြင့် Address Book, Stand Alone Clinic Management System, Stand Alone POS အစရှိသဖြင့် Stand Alone Application များဆိုပါက Embedded Derby အား ရွေးချယ်သင့်ပါသည်။ နမှုနာ အနေနှင့် Student Entity အား ရေးသားကြည့်ပါမည်။
@Entity
public class Student implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
    
    private String name;
    private String phone;
    private String address;

    // constructor, getter and setter

အထက်ပါအတိုင်း ID Column တွင် GeneratedValue ၏ Attribute strategy တွင် GenerationType.AUTO ဟု ရေးသားထားပါသည်။ ပြီးပါက Test Class တစ်ခုအား ရေးသား၍ Run ကြည့်ပါက အောက်ပါအတိုင်း DB အတွင်းတွင် Table များအား တည်ဆောက်သွားနိုင်မည် ဖြစ်သည်။


အထက်ဖော်ပြပါအတိုင်း STUDENT Table အပြင် SEQUENCE Table အားလည်း တည်ဆောက်သွားသည်ကို တွေ့ရမည် ဖြစ်သည်။ Derby Database သည် MySQL ကဲ့သို့ Auto Increment အားအသုံးပြု၍ မရသောကြောင့် SEQUENCE Table အား တည်ဆောက်၍ ID အား Generate လုပ်ကာ အသုံးပြုသွားခြင်း ဖြစ်၏။

SEQUENCE Table ၏ ဖွဲ့စည်းပုံမှာ အောက်ပါအတိုင်း ဖြစ်၏။ Column အနေနှင့် SEQ_NAME နှင့် SEQ_COUNT ဟူ၍ နှစ်ခုပါဝင် ပါသည်။ ၎င်းအတွင်းတွင် SEQ_GEN နှင့် 50 အား တန်ဖိုးအသစ်အနေနှင့် INSERT လုပ်ထားခဲ့ပါသည်။

SEQ_GEN ဆိုသည်မှာ အသုံးပြုမည့် SEQUENCE ၏ အမည် ဖြစ်ပြီး၊ SEQ_COUNT မှာ နောက်ဆုံး SEQUENCE ၏ နံပါတ်ဖြစ်၏။ ဤနမှုနာတွင် Record တစ်ကြောင်းတည်းသာ Insert လုပ်ခဲ့သော်လည်း တန်ဖိုးမှာ 50 ဖြစ်နေပါသည်။ အဘယ်ကြောင့် ဆိုသော် Derby Sequence များ၏ Default Allocation Size မှာ 50 ဖြစ်သောကြောင့်၊ တစ်ကြောင်းတည်းသာ Insert လုပ်ခဲ့သော်လည်း တန်ဖိုးမှာ 50 ဖြစ်နေခြင်း ဖြစ်ပါသည်။ အကယ်၍ နောက်တစ်ကြောင်း Insert လုပ်ကြည့်ပါက တန်ဖိုးမှာ 100 ဖြစ်သွားမည် ဖြစ်သည်။



SEQUENCE Strategy အား အသုံးပြုခြင်း


အထက်တွင် AUTO အား အသုံးပြု၍ SEQUENCE အား Default အတိုင်း အသုံးပြုပုံကို ဖော်ပြခဲ့ပါသည်။ ဆက်လက်၍ SEQUENCE အား ရွေးချယ်၍ အသုံးပြုကြည့်ပါဦးမည်။ SEQUENCE Strategy အား အသုံးပြုပါက Derby Database အတွင်းတွင် Sequence Object အား တည်ဆောက်၍ အသုံးပြုမည် ဖြစ်ပါသည်။

Default အတိုင်း အသုံးပြုမည် ဆိုပါက SEQ_GEN_SEQUENCE အမည်နှင့် Sequence Object အား တည်ဆောက်၍ အသုံးပြုမည် ဖြစ်သည်။ Initial Value ၏ Default တန်ဖိုးမှာ 1 ဖြစ်ပြီး Allocation Size မှာ 50 ဖြစ်သည်။

Default တန်ဖိုးအား ပြုပြင်၍ အသုံးပြုလိုပါက @SequenceGenerator အား အသုံးပြုနိုင်မည် ဖြစ်သည်။


SequenceGenerator တွင် သတ်မှတ်နိုင်သော Attribute များမှာ အောက်ပါအတိုင်း ဖြစ်၏။

  • name : Sequence Generator ၏ အမည်
  • sequenceName : Sequence Object ၏ အမည်
  • schema : Schema ၏ အမည်၊ Default အတိုင်းဆိုပါက လက်ရှိ Schema အား အသုံးပြုမည် ဖြစ်သည်။
  • catalog : Catalog ၏ အမည်၊ Default အတိုင်းဆိုပါက လက်ရှိ Catalog အား အသုံးပြုမည် ဖြစ်သည်။
  • allocationSize : တစ်ခါ ရယူနိုင်သည့် Sequence အရေအတွက်၊ Default တန်ဖိုးမှာ 50 ဖြစ်သည်။
  • initialValue : ပထမဆုံး Sequence ၏ တန်ဖိုး၊ Default တန်ဖိုးမှာ 1 ဖြစ်ပါသည်။


အောက်ဖော်ပြပါ နမှုနာထဲတွင် SequenceGenerator အား အသုံးပြုထားပါသည်။
@Entity
public class Student implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "SEQ_GEN")
    @SequenceGenerator(name = "SEQ_GEN", sequenceName = "STUDENT_SQ", 
        allocationSize = 1, initialValue = 1)
    private int id;
    
    private String name;
    private String phone;
    private String address;
    
    // constructor, getter and setter

အထက်ပါနမှုနာထဲတွင် schema နှင့် catalog ၏ တန်ဖိုးအား default အတိုင်း အသုံးပြုသောကြောင့် အထွေအထူး မရေးသားတော့ပါ။ name တွင် အသုံးပြုမည့် Generator ၏ အမည်အား ရေးသားပြီး၊ sequenceName တွင် အသုံးပြုမည့် Sequence Object ၏ အမည်အား ရေးသားပါသည်။

allocationSize တွင် ဤနေရာ၌ နံပါတ်အား တစ်ခုစီ တက်စေလိုသောကြောင့် 1 ဟု ရေးသားထားပြီး၊ initialValue ၏ တန်ဖိုးအား 1  ဟု ရေးသားပါသည်။ အဆိုပါအတိုင်းရေးသား၍ Test Program အား Run ကြည့်ပါက ပထမဆုံးအကြိမ်တွင် Sequence Object အား မတွေ့ပါဟု Error Message ဖြစ်ပေါ်မည် ဖြစ်သော်လည်း စိတ်မပူပါနှင့်။ Warning ဆန်သော Error ဖြစ်ပါသည်။ JPA သည် Sequence Object အား မတွေ့ပါက အသစ်တည်ဆောက်၍ အသုံးပြုသွားမည် ဖြစ်သောကြောင့် နောက်အကြိမ်များတွင် Error ထပ်ပေါ်လာမည် မဟုတ်တော့ပါ။


TABLE Strategy အား အသုံးပြုခြင်း


TABLE Strategy သည် Enterprise Application များအတွက် အသင့်တော်ဆုံးသော နည်းလမ်းဖြစ်ပါသည်။ အလွန်ပင် Flexible ဖြစ်ပြီး၊ Sequence Table အား အသုံးပြုထားသောကြောင့် မည်သည့် Database Management System မှာမဆို အသုံးပြုနိုင်ပါသည်။

TABLE Strategy အား အသုံးပြုရာတွင် Default အတိုင်း ရေးသားပါက Database အတွင်းတွင် SEQUENCE အမည်နှင့် Sequence Table အား တည်ဆောက်၍ အသုံးပြုမည် ဖြစ်သည်။ Default တန်ဖိုးမှာ AUTO Strategy တွင် စမ်းသပ်ခဲ့သကဲ့သို့ Primary Key Column အား SEQ_NAME ဖြစ်ပြီး၊ Value တန်ဖိုးမှာ SEQ_COUNT ဖြစ်ပါသည်။ Default အတိုင်းအသုံးပြုပါက Allocation Size မှာ 50 ဖြစ်ပြီး Initial Value မှာ 1 ဖြစ်၏။ Primary Key Value အား SEQ_GEN_TABLE ဟု ရေးသား အသုံးပြုမည် ဖြစ်သည်။

Default တန်ဖိုးများအား ပြောင်းလဲ၍ အသုံးပြုလိုပါက @TableGenerator Annotation အား အသုံးပြုနိုင်မည် ဖြစ်သည်။


@TableGenerator Annotation တွင် အသုံးပြုနိုင်သော Attribute များမှာ အောက်ပါအတိုင်းဖြစ်ပါသည်။

  • name : Generator ၏ အမည်
  • table : Identity များအား သိမ်းဆည်းပေးမည့် Table ၏ အမည်
  • schema : Identity Table အား တည်ဆောက်မည့် Schema အမည်
  • catalog : အသုံးပြုမည့် Catalog ၏ အမည်
  • pkColumnName : Primary Key Column ၏ အမည်
  • valueColumnName : Value Column ၏ အမည်
  • pkColumnValue :  Primary Key Column ၏ တန်ဖိုး
  • allocationSize : တစ်ခါ ရယူနိုင်သည့် Sequence အရေအတွက်
  • initialValue : စစဦးချင်းအသုံးပြုမည့် Sequence တန်ဖိုး


အောက်နမှုနာထဲတွင် TableGenerator အား အသုံးပြုထားပါသည်။
@Entity
public class Student implements Serializable {

    @Id
    @GeneratedValue(strategy=TABLE, generator = "SEQ_GEN")
    @TableGenerator(name = "SEQ_GEN", 
        table = "SEQ_TBL", allocationSize = 1, 
        initialValue = 1001, pkColumnName = "seq_id", 
        valueColumnName = "seq_value")
    private int id;
    
    private String name;
    private String phone;
    private String address;
    
    // constructor, getter and setter

အထက် နမှုနာအတိုင်း စမ်းသပ်ကြည့်သောအခါ အောက်ပါအတိုင်း Sequence Table အား တည်ဆောက် ပေးနိုင်သည်ကို တွေ့ရပါသည်။


SEQUENCE Strategy ကဲ့သို့ပင် ပထမဦးဆုံး တစ်ခေါက်တွင် Table အတွင်းမှ တန်ဖိုးအား Delete လုပ်၍ မရကြောင်း Error Message ထွက်ပေါ်မည် ဖြစ်သော်လဲ အလိုအလျှောက် Insert လုပ်သွားမည် ဖြစ်သောကြောင့် ပြဿနာမရှိပါ။ နောက်အခေါက်များတွင် Error တွက်ပေါ်တော့မည် မဟုတ်ပါ။

ယခုတစ်ခေါက်တွင် Simple ID Column များနှင့် ပတ်သက်၍ ဖော်ပြခဲ့ပါသည်။ သို့ရာတွင် လက်တွေ့ Database အား အသုံးပြုရာတွင် Primary Key Column မှာ တစ်ခုတည်း ရှိသည်မဟုတ်ပါ။ Business Needs အရ ရက်စွဲ Column အများအား စုပေါင်း၍ Primary Key အနေနှင့် အသုံးပြုသည့်အခါများလည်း ရှိ၏။ နောက် တစ်ခေါက်တွင် Composite Key Column နှင့် ပတ်သက်၍ ဆက်လက်ဖော်ပြသွားပါ ဦးမည်။


လေးစားစွာဖြင့်
မင်းလွင်

No comments:

Post a Comment