<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    千里冰封
    JAVA 濃香四溢
    posts - 151,comments - 2801,trackbacks - 0

    單個(gè)實(shí)體BEAN的映射到數(shù)據(jù)庫(kù)的方式很簡(jiǎn)單,但是如果我們的實(shí)體BEAN之間存在著繼承關(guān)系呢?在數(shù)據(jù)庫(kù)里面將如何表現(xiàn)這種繼承關(guān)系?
    JAVA持久化規(guī)范里面提供了三種方式去處理繼承實(shí)體的映射方式:
    一,所有繼承層次共單獨(dú)一張表
    二,每個(gè)具體的類(lèi)一個(gè)單獨(dú)的表
    三,每個(gè)子類(lèi)一張表

    為了更好的舉例說(shuō)明,我們構(gòu)造出如下的繼承層次,以做為例子使用。


    我們今天先來(lái)看看第一種方式,那就是所有的繼承層次共單獨(dú)一張表。

    一,所有繼承層次共單獨(dú)一張表

    在這種模式中,一張數(shù)據(jù)庫(kù)的表里面將放入所有的繼承層次的類(lèi)的屬性,在我們的例子中,我們的Person,Customer,Empolyee的實(shí)體都將映射在同一張表里面,表的結(jié)構(gòu)如下所示:

     

    create table PERSON_HIERARCHY 
     (
       id 
    integer primary key not null,
       firstName 
    varchar(255),
       lastName 
    varchar(255),
       street 
    varchar(255),
       city 
    varchar(255),
       state 
    varchar(255),
       zip 
    varchar(255),
       employeeId 
    integer,
       DISCRIMINATOR 
    varchar(31not null
    );

     

    正是因?yàn)槲覀儼阉欣^承層次的實(shí)體都放在同一張表里面,所以我們需要一個(gè)來(lái)標(biāo)志具體類(lèi)型的列,它指示當(dāng)前記錄是屬于哪個(gè)類(lèi)的,這樣EntityManager好還原成相應(yīng)的實(shí)體BEAN而不致于出錯(cuò)。我們還是先看看代碼是如何告訴EntityManager它的繼承實(shí)現(xiàn)方式的。

     

    @Entity
    @Table(name
    ="PERSON_HIERARCHY")
    @Inheritance(strategy
    =InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name
    ="DISCRIMINATOR",
                         discriminatorType
    =DiscriminatorType.STRING)
    @DiscriminatorValue(
    "PERSON")
    public class Person {
       
    private int id;
       
    private String firstName;
       
    private String lastName;

       @Id @GeneratedValue
       
    public int getId( ) { return id; }
       
    public void setId(int id) { this.id = id; }

       
    public String getFirstName( ) { return firstName; }
       
    public void setFirstName(String first) { this.firstName = first; }

       
    public String getLastName( ) { return lastName; }
       
    public void setLastName(String last) { this.lastName = last; }
    }

     

     @javax.persistence.Inheritance注釋就是用來(lái)聲明繼承的時(shí)候它的持久化策略的,它的聲明如下:
     

     package javax.persistence;

    @Target(TYPE) @Retention(RUNTIME)
    public @interface Inheritance {
       InheritanceType strategy( ) 
    default SINGLE_TABLE; 

    }

    public enum InheritanceType {
       SINGLE_TABLE, JOINED, TABLE_PER_CLASS
    }

     

    在這里,strategy()方法定義了我們所使用的繼承映射模式,我們?cè)谶@里用的是單獨(dú)一張表放所有的繼承層次實(shí)體,所以我們使用了枚舉InheritanceType.SINGLE_TABLE,有一點(diǎn)我們需要注意的是,@Inheritance這個(gè)注釋僅僅只在繼承層次的根類(lèi)上是必須要有的,一般它的子類(lèi)都沒(méi)有必要寫(xiě)這個(gè)注釋?zhuān)悄阆敫淖兝^承映射的實(shí)現(xiàn)方式。

     

    package javax.persistence;

    @Target(TYPE) @Retention(RUNTIME)
    public @interface DiscriminatorColumn
       String name( ) 
    default "DTYPE";
       DiscriminatorType discriminatorType( ) 
    default STRING;
       String columnDefinition( ) 
    default "";
       
    int length( ) default 10;
    }

     

    因?yàn)槲覀兪褂靡粡埍韥?lái)保存所有繼承層次的類(lèi),所以我們需要一個(gè)某種方式好讓持久化實(shí)現(xiàn)者知道如何去分辨我們真正想要保存的對(duì)象是屬于哪個(gè)繼承層次的,我們靠從一個(gè)辨別器的列里面去獲得這一點(diǎn)。@javax.persistence.DiscriminatorColumn這個(gè)流釋就是指示我們哪個(gè)類(lèi)將會(huì)存儲(chǔ)辨別器,看著注釋我們可以知道,這個(gè)注釋并不是必要的,因?yàn)樗宽?xiàng)都有默認(rèn)值,對(duì)于辨別器的類(lèi)型,默認(rèn)是String類(lèi)型,我們除了String類(lèi)型之外,還可以用如下幾個(gè)類(lèi)型:char,Integer。

     

    package javax.persistence;

    @Target(TYPE) @Retention(RUNTIME)
    public @interface DiscriminatorValue {
       String value( )
    }

     

    這個(gè)注釋是指示我們辨別器的值是多少,這個(gè)只是我們提示辨別器的類(lèi)型是String的時(shí)候,還需要我們?nèi)?xiě),如果類(lèi)型是int或者char的時(shí)候,是不需要我們?nèi)ヌ岫ㄋ鼈兊谋鎰e器的值的。所以最好還是使用char或者int類(lèi)型,以使我們從這些細(xì)節(jié)方面解放出來(lái)。

    在我們建立了這種映射策略之后,子類(lèi)的定義就顯得簡(jiǎn)單多了:

     

    @Entity
    @DiscriminatorValue 
    (
    "CUST")
    public class Customer extends Person {
       
    private String street;
       
    private String city;
       
    private String state;
       
    private String zip;
       
    public String getStreet( ) { return street; }
       
    public void setStreet(String street) { this.street = street; }

    }

     

    我們也可以都用默認(rèn)的值,什么額外的注釋都不要加

     

    @Entity
    public class Employee extends Customer {
       
    private int employeeId;

       
    public int getEmployeeId( ) { return employeeId; }
       
    public void setEmployeeId(int id) { employeeId = id; }
    }

     

    在這個(gè)例子里面,Customer實(shí)體的辨別器列的值設(shè)為CUST,這是我們?nèi)藶樵O(shè)置的。當(dāng)然我們?nèi)绻辉O(shè)置的話(huà),就像Employee,那么它的辨別器列的值就會(huì)被設(shè)為Employee, 因?yàn)樗念?lèi)的名字就是Employee。

    優(yōu)點(diǎn):
    SINGLE_TABLE的映射策略是最簡(jiǎn)單的實(shí)現(xiàn)并且性能來(lái)說(shuō),也是比其它兩個(gè)要高。因?yàn)樗挥幸粡埍硇枰ヌ幚怼3志没娌恍枰プ鋈魏螐?fù)雜的連接組合或者子查詢(xún)等等,因?yàn)樗械牡臄?shù)據(jù)都存在一張表里面
    缺點(diǎn):
    這種策略最大的一個(gè)缺點(diǎn)就是所有的有關(guān)子類(lèi)的屬性的映射列都必須是nullable,因?yàn)槟悴豢赡茏屢粋€(gè)類(lèi)擁有所有的屬性,畢竟這些屬性是所有的類(lèi)加起來(lái)的,所以你不能為你的類(lèi)加上NOT NULL的約束。還有,因?yàn)樗凶宇?lèi)的屬性列對(duì)于某些實(shí)體類(lèi)來(lái)說(shuō)都是沒(méi)有用的,所以SINGLE_TABLE 策略也是不符合規(guī)范的。


     




    盡管千里冰封
    依然擁有晴空

    你我共同品味JAVA的濃香.
    posted on 2007-10-08 00:11 千里冰封 閱讀(949) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JAVAEE
    主站蜘蛛池模板: 久久亚洲精品国产精品| 最近免费中文字幕大全免费| 黄网站色视频免费观看45分钟| 久久久久亚洲国产| tom影院亚洲国产一区二区| 亚洲国产品综合人成综合网站| 亚洲免费视频播放| 国产成人精品日本亚洲专一区| 亚洲视频无码高清在线| 亚洲欧洲日产国码久在线| 亚洲av无码专区在线电影| WWW亚洲色大成网络.COM| 免费看黄福利app导航看一下黄色录像| 黄人成a动漫片免费网站| h片在线观看免费| 两个人的视频www免费| 免费毛片在线看不用播放器| 免费人成毛片动漫在线播放| 99久久精品免费视频| 在线永久看片免费的视频| 一二三四免费观看在线电影 | 一区二区三区在线免费观看视频| 午夜不卡AV免费| 国产一区二区三区免费观看在线| 久久久久国产免费| 无人在线直播免费观看| 日韩精品视频免费在线观看| 日本中文一区二区三区亚洲| 亚洲中文字幕丝袜制服一区| 亚洲第一区香蕉_国产a| 亚洲永久在线观看| 免费精品视频在线| 无码国产精品一区二区免费模式| 中文字幕无码视频手机免费看| 国产精品jizz在线观看免费| 久久精品亚洲福利| 亚洲国产精品网站久久| 国产成人 亚洲欧洲| a毛片视频免费观看影院| 国产一卡二卡3卡四卡免费| 免费人成视频x8x8入口|