Sealyu

          --- 博客已遷移至: http://www.sealyu.com/blog

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            618 隨筆 :: 87 文章 :: 225 評(píng)論 :: 0 Trackbacks
          <2009年1月>
          28293031123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(14)

          隨筆分類

          隨筆檔案

          友情鏈接

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          因?yàn)殛P(guān)系數(shù)據(jù)庫(kù)的表之間不存在繼承關(guān)系,Entity 提供三種基本的繼承映射策略:
          每個(gè)類分層結(jié)構(gòu)一張表(table per class hierarchy)
          每個(gè)子類一張表(table per subclass)
          每個(gè)具體類一張表(table per concrete class)

          一、每個(gè)類分層結(jié)構(gòu)一張表(table per class hierarchy)
                 這種映射方式只需為基類創(chuàng)建一個(gè)表即可。在表中不僅提供基類所有屬性對(duì)應(yīng)的字段,還要提供所有子類屬性對(duì)應(yīng)的字段,此外還需要一個(gè)字段用于區(qū)分子類的具體類型
                 要使用每個(gè)類分層結(jié)構(gòu)一張表(table per class hierarchy) 策略,需要把@javax.persistence.Inheritance 注釋的strategy屬性設(shè)置為InheritanceType.SINGLE_TABLE。除非你要改變子類的映射策略,否則@Inheritance 注釋只能放在繼承層次的基類。通過鑒別字段的值,持久化引掣可以區(qū)分出各個(gè)類,并且知道每個(gè)類對(duì)應(yīng)那些字段。鑒別字段通過@javax.persistence.DiscriminatorColumn 注釋進(jìn)行定義,name 屬性定義鑒別字段的列名discriminatorType 屬性定義鑒別字段的類型(可選值有:String, Char, Integer),如果鑒別字段的類型為String 或Char,可以用length 屬性定義其長(zhǎng)度。@DiscriminatorValue 注釋為繼承關(guān)系中的每個(gè)類定義鑒別值,如果不指定鑒別值,默認(rèn)采用類名
          例:
              @SuppressWarnings("serial")
              @Entity
              @Table(name="Vehicle_Hierarchy")
              @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
              @DiscriminatorColumn(name="Discriminator",
                                                   discriminatorType = DiscriminatorType.STRING,
                                                   length=30)
              @DiscriminatorValue("Vehicle")
              public class Vehicle implements Serializable{       //基類
              private Long id;
              private Short speed;//速度
              @Id
              @GeneratedValue
              @Column(columnDefinition="integer")//指定使用適配Integer長(zhǎng)度的數(shù)據(jù)類型
              public Long getId() {
              return id;
              }
              public void setId(Long id) {
              this.id = id;
              }

              @SuppressWarnings("serial")
              @Entity
              @DiscriminatorValue("Car")
              public class Car extends Vehicle{        //Vehicle的子類
              private String engine;//發(fā)動(dòng)機(jī)
              @Column(nullable=true,length=30)
              public String getEngine() {
              return engine;
              }
              public void setEngine(String engine) {
              this.engine = engine;
                  }
              }


               @SuppressWarnings("serial")
               @Entity
               @DiscriminatorValue("Camion")
               public class Camion extends Car{         //Car的子類
               private String container;//集裝箱
               @Column(nullable=true,length=30)
               public String getContainer() {
               return container;
               }
               public void setContainer(String container) {
               this.container = container;
                    }
               }
          分析:
                 可 以看出,每個(gè)子類沒有單獨(dú)的映射,在數(shù)據(jù)庫(kù)中沒有對(duì)應(yīng)的表存在。而只有一個(gè)記錄所有自身屬性和子類所有屬性的表,在基類為Vehicle 的時(shí)候,Discriminator 字段的值將為Vehicle,在子類為Car 的時(shí)候,Discriminator 字段的值將為Car,子類為Camion 的時(shí)候,Discriminator 字段的值將為Camion。那么,如果業(yè)務(wù)邏輯要求Car 對(duì)象的engine 屬性不允許為null,顯然無法在Vehicle_Hierarchy 表中為engine 字段定義not null 約束,可見這種映射方式無法保證關(guān)系數(shù)據(jù)模型的數(shù)據(jù)完整性。

          二、每個(gè)類分層結(jié)構(gòu)一張表(table per class hierarchy)
                 這種映射方式為每個(gè)類創(chuàng)建一個(gè)表。在每個(gè)類對(duì)應(yīng)的表中只需包含和這個(gè)類本身的屬性對(duì)應(yīng)的字段,子類對(duì)應(yīng)的表參照父類對(duì)應(yīng)的表,使用每個(gè)子類一張表 (table per subclass)策略,需要把@javax.persistence.Inheritance 注釋的strategy 屬性設(shè)置為InheritanceType.JOINED

               @SuppressWarnings("serial")
               @Entity
               @Inheritance(strategy=InheritanceType.JOINED)
               @Table(name="Vehicle")
               public class Vehicle implements Serializable{      //基類
               private Long id;
               private Short speed;//速度
               @Id
               @GeneratedValue
               @Column(columnDefinition="integer")
               public Long getId() {
               return id;
               }
               public void setId(Long id) {
               this.id = id;
               }
               public Short getSpeed() {
               return speed;
               }
               public void setSpeed(Short speed) {
               this.speed = speed;
               }
               }

               @SuppressWarnings("serial")
               @Entity
               @Table(name="Car")
               @PrimaryKeyJoinColumn(name="CarID")     //把主鍵對(duì)應(yīng)的列名更改為CarID
               public class Car extends Vehicle{                 //Vehicle的子類
               private String engine;//發(fā)動(dòng)機(jī)
               @Column(nullable=true,length=30)
               public String getEngine() {
               return engine;
               }
               public void setEngine(String engine) {
               this.engine = engine;
               }
               }

               @SuppressWarnings("serial")
               @Entity
               @Table(name="Camion")
               @PrimaryKeyJoinColumn(name="CamionID")     //把主鍵對(duì)應(yīng)的列名更改為CamionID
               public class Camion extends Car{                    //Car的子類
               private String container;
               @Column(nullable=true,length=30)
               public String getContainer() {
               return container;
               }
               public void setContainer(String container) {
               this.container = container;
               }
               }
                  這種映射方式支持多態(tài)關(guān)聯(lián)和多態(tài)查詢,而且符合關(guān)系數(shù)據(jù)模型的常規(guī)設(shè)計(jì)規(guī)則。在這種策略中你可以對(duì)子類的屬性對(duì)應(yīng)的字段定義not null 約束。該策略的缺點(diǎn):
                  它的查詢性能不如上面介紹的映射策略。在這種映射策略下,必須通過表的內(nèi)連接或左外連接來實(shí)現(xiàn)多態(tài)查詢和多態(tài)關(guān)聯(lián)。
          選擇原則:子類屬性非常多,需要對(duì)子類某些屬性對(duì)應(yīng)的字段進(jìn)行not null 約束,且對(duì)性能要求不是很嚴(yán)格時(shí),優(yōu)先選擇該策略


          三、每個(gè)具體類一張表(table per concrete class)
                 這種映射方式為每個(gè)類創(chuàng)建一個(gè)表。在每個(gè)類對(duì)應(yīng)的表中包含和這個(gè)類所有屬性(包括從超類繼承的屬性)對(duì)應(yīng)的字段,使用每個(gè)具體類一張表(table per concrete class)策略,需要把@javax.persistence.Inheritance 注釋的strategy 屬性設(shè)置為InheritanceType.TABLE_PER_CLASS

                  注意:一旦使用這種策略就意味著你不能使用AUTO generator 和IDENTITY generator,即主鍵值不能采用數(shù)據(jù)庫(kù)自動(dòng)生成.

               @SuppressWarnings("serial")
               @Entity
               @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
               @Table(name="Vehicle")
               public class Vehicle implements Serializable{            //基類
               private Long id;
               private Short speed;//速度
               @Id
               @Column(columnDefinition="integer")
               public Long getId() {
               return id;
               }
               public void setId(Long id) {
               this.id = id;
               }
               public Short getSpeed() {
               return speed;
               }
               public void setSpeed(Short speed) {
               this.speed = speed;
               }
               }

               @SuppressWarnings("serial")
               @Entity
               @Table(name="Car")
              public class Car extends Vehicle{               //Vehicle的子類
               private String engine;//發(fā)動(dòng)機(jī)
               @Column(nullable=true,length=30)
               public String getEngine() {
               return engine;
               }
               public void setEngine(String engine) {
               this.engine = engine;
               }
               }

               @SuppressWarnings("serial")
               @Entity
               @Table(name="Camion")
               public class Camion extends Car{              //Car的子類
               private String container;//集裝箱
               @Column(nullable=true,length=30)
               public String getContainer() {
               return container;
               }
               public void setContainer(String container) {
               this.container = container;
               }
               }

          注意:在查詢時(shí),例如: from Vehicle v
                   查詢所有Vehicle時(shí),因?yàn)樗亲罾^承樹中的根,查詢結(jié)果會(huì)得到所有繼承于Vehicle類的記錄
          (構(gòu)造的SQL Where部分:where Discriminator in ('Car', 'Camion'))
                   delete from Vehicle v
                   執(zhí)行該操作會(huì)刪除自身對(duì)應(yīng)記錄,還會(huì)刪除所有繼承Vehicle的記錄,因?yàn)樗亲罾^承樹中的根,就相當(dāng)于清除整個(gè)表的數(shù)據(jù)

          該策略的優(yōu)點(diǎn):
                               在這種策略中你可以對(duì)子類的屬性對(duì)應(yīng)的字段定義not null 約束。
          該策略的缺點(diǎn):
                               不符合關(guān)系數(shù)據(jù)模型的常規(guī)設(shè)計(jì)規(guī)則,每個(gè)表中都存在屬于基類的多余的字段。同時(shí),為了支持策略的映射,持久化管理者需要決定使用什么方法,一種方法是在 entity 載入或多態(tài)關(guān)聯(lián)時(shí),容器使用多次查詢?nèi)?shí)現(xiàn),這種方法需要對(duì)數(shù)據(jù)庫(kù)做幾次來往查詢,非常影響執(zhí)行效率。另一種方法是容器通過使用SQLUNIOU 查詢來實(shí)現(xiàn)這種策略。
          選擇原則:
                               除非你的現(xiàn)實(shí)情況必須使用這種策略,一般情況下不要選擇。
          posted on 2009-01-05 14:18 seal 閱讀(1215) 評(píng)論(2)  編輯  收藏 所屬分類: HibernateEJB

          評(píng)論

          # re: EJB/JPA繼承詳解(轉(zhuǎn))[未登錄] 2009-01-06 22:10 x
          復(fù)雜。  回復(fù)  更多評(píng)論
            

          # re: EJB/JPA繼承詳解(轉(zhuǎn))[未登錄] 2011-12-20 16:21 無名
          @x
          而且不知哪種更好一些  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 临夏县| 年辖:市辖区| 芮城县| 嵊泗县| 都兰县| 宁明县| 孟津县| 夏邑县| 神木县| 永顺县| 林周县| 任丘市| 奉贤区| 淮阳县| 青海省| 嫩江县| 石棉县| 修文县| 谷城县| 石阡县| 海丰县| 北碚区| 永嘉县| 五寨县| 河池市| 巧家县| 松滋市| 浮梁县| 马边| 当阳市| 营口市| 云南省| 连云港市| 湾仔区| 荆州市| 富顺县| 依安县| 寻乌县| 揭东县| 内江市| 泸州市|