神奇好望角 The Magical Cape of Good Hope

          庸人不必自擾,智者何需千慮?
          posts - 26, comments - 50, trackbacks - 0, articles - 11
            BlogJava :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理

          實體間的多對多的關(guān)聯(lián)需要一張關(guān)聯(lián)表。如果直接使用 ManyToMany 來映射,JPA 就會隱式地幫我們自動管理關(guān)聯(lián)表,代碼寫出來和其他類型的關(guān)聯(lián)差別不大。例如,某州炒房團需要一個炒房跟蹤系統(tǒng),那么該系統(tǒng)中的炒房客和房子就是多對多的關(guān)系:

                  public class Speculator implements Serializable {
                      @Id
                      private Integer id;
                      @ManyToMany
                      @JoinTable(joinColumns = @JoinColumn(name = "speculator_id"),
                              inverseJoinColumns = @JoinColumn(name = "house_id"))
                      private List<House> houses;
                      // 此處省略若干行
                  }
          
                  public class House implements Serializable {
                      @Id
                      private Integer id;
                      @ManyToMany(mappedBy = "houses")
                      private List<Speculator> speculators;
                      // 此處省略若干行
                  }
              

          如果炒房客 s 要賣掉房子 h(嚴格點說是賣掉房子的產(chǎn)權(quán)部分),那么系統(tǒng)執(zhí)行的代碼差不多就是 s.getHouses().remove(h)??此坪唵?,然而底層的操作卻性能低下:JPA 會先從數(shù)據(jù)庫中取出炒房客的所有房產(chǎn)(s.getHouses()),然后再刪除指定的那套房子;從數(shù)據(jù)庫層面上看,這將先從關(guān)聯(lián)表(speculator_house)中找到該炒房客的所有房子的外鍵,然后從 house 表載入這些 House 對象,最后才從 speculator_house 刪除關(guān)聯(lián)。在 ORM 出現(xiàn)前,這種操作只需要改關(guān)聯(lián)表,根本不用關(guān)心其他房子。這種簡單的多對多映射寫法將關(guān)聯(lián)表隱藏起來,雖然簡化了代碼,卻也可能帶來性能隱患。

          很自然地可以想到,如果把關(guān)聯(lián)表也映射成實體類,就能解決這個問題。speculator_house 包含兩個外鍵,可用作聯(lián)合主鍵。如果把它映射為 SpeculatorHouse 類,則該類與 SpeculatorHouse 都是多對一的關(guān)系。關(guān)聯(lián)表實體類的代碼如下(EmbeddedId 的映射技巧見《JPA 應(yīng)用技巧 2:主鍵外鍵合體映射》):

                  @Embeddable
                  public class SpeculatorHouseId implements Serializable {
                      private Integer speculatorId;
                      private Integer houseId;
                      // 此處省略若干行
                  }
          
                  @Entity
                  @Table(name = "speculator_house")
                  public class SpeculatorHouse implements Serializable {
                      @EmbeddedId
                      private SpeculatorHouseId id;
                      @MapsId("speculatorId")
                      @ManyToOne
                      private Speculator speculator;
                      @MapsId("houseId")
                      @ManyToOne
                      private House house;
                      // 此處省略若干行
                  }
              

          SpeculatorHouse 也要增加相應(yīng)的關(guān)聯(lián)信息:

                  public class Speculator implements Serializable {
                      @Id
                      private Integer id;
                      @ManyToMany
                      @JoinTable(joinColumns = @JoinColumn(name = "speculator_id"),
                              inverseJoinColumns = @JoinColumn(name = "house_id"))
                      private List<House> houses;
                      @OneToMany(mappedBy = "speculator")
                      private List<SpeculatorHouse> speculatorHouses;
                      // 此處省略若干行
                  }
          
                  public class House implements Serializable {
                      @Id
                      private Integer id;
                      @ManyToMany(mappedBy = "houses")
                      private List<Speculator> speculators;
                      @OneToMany(mappedBy = "house")
                      private List<SpeculatorHouse> speculatorHouses;
                      // 此處省略若干行
                  }
              

          這樣既保留了多對多關(guān)系,又映射了關(guān)聯(lián)表,然后就可以根據(jù)實際情況選擇隱式或顯示的關(guān)聯(lián)表管理。例如,要得到一個炒房客的全部房子,就使用隱式管理:s.getHouses();而要刪除炒房客和某套房子的關(guān)聯(lián),則用顯示管理:delete from SpeculatorHouse sh where sh.speculator = :s and sh.house = :h


          評論

          # re: JPA 應(yīng)用技巧 3:映射多對多的關(guān)聯(lián)表[未登錄]  回復(fù)  更多評論   

          2012-06-14 16:05 by DD
          但是,我按照你這樣配起來,怎么刪speculator?。。我現(xiàn)在無法刪除speculator。

          # re: JPA 應(yīng)用技巧 3:映射多對多的關(guān)聯(lián)表  回復(fù)  更多評論   

          2012-10-11 15:06 by merge
          對于中間表操作描述詳細,收藏了!
          主站蜘蛛池模板: 广东省| 太仓市| 桐城市| 平陆县| 尚义县| 佳木斯市| 揭东县| 乌恰县| 彭州市| 呈贡县| 宾川县| 习水县| 老河口市| 陕西省| 京山县| 福鼎市| 延庆县| 金溪县| 漳州市| 顺义区| 岳池县| 循化| 泸西县| 安阳市| 北京市| 宁陵县| 法库县| 建始县| 博湖县| 铁岭市| 慈溪市| 邻水| 普格县| 民勤县| 秀山| 玉田县| 高台县| 镇远县| 沅江市| 德庆县| 高青县|