神奇好望角 The Magical Cape of Good Hope

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

          JPA 應(yīng)用技巧 2:主鍵外鍵合體映射

          Posted on 2011-09-13 11:27 蜀山兆孨龘 閱讀(3906) 評論(0)  編輯  收藏 所屬分類: Java EE

          考慮兩個具有一對一關(guān)聯(lián)的實體類,受控方除了有一個自己的主鍵,還有一個引用主控方的外鍵。如果主控方和受控方是同生同滅的關(guān)系,換句話說,雙方的一對一關(guān)聯(lián)一旦確立就不可更改,就可以考慮讓雙方共享相同的主鍵,簡化受控方的表結(jié)構(gòu)。下面就讓樓主通過實例來說明如何用 JPA 2.0 來實現(xiàn)這種映射。

          盯著眼前的電腦,樓主想到了一個也許不太貼切的例子:員工和公司配的電腦的關(guān)系。員工的主鍵就是工號。雖然電腦可能被換掉,但電腦實體完全可以用工號做主鍵,只是把電腦配置的詳細信息改掉而已。此處的難點就在與如何將電腦的主鍵字段同時映射一個員工,請看樓主是怎么一步步推導(dǎo)出來的。

          一開始是最想當(dāng)然的寫法:

                  public class Computer implements Serializable {
                      @Id
                      @OneToOne
                      private Employee employee;
                      // 此處省略若干行
                  }
              

          然而根據(jù)規(guī)范,只有這些類型可以作為主鍵:Java 原始類型(例如 int)、原始包裝類型(例如 Integer)、Stringjava.util.Datejava.sql.Date、 java.math.BigDecimaljava.math.BigInteger。所以直接拿 Employee 做主鍵是不行的。順便提一下,也許某些 JPA 實現(xiàn)自己做了擴展,使得可以直接拿實體類做主鍵,這已經(jīng)超出了 JPA 規(guī)范的范疇,此處不討論。

          直接映射是行不通了,那有什么間接的方式嗎?這時樓主想起了一個特殊的注解:EmbeddedId。該注解的本意是用于聯(lián)合主鍵,不過變通一下,是否可以將 Employee 包裝進一個嵌入式主鍵,然后再將這個嵌入式主鍵作為 Computer 的主鍵以達到目的?帶著這種想法,樓主有了下面的代碼:

                  @Embeddable
                  public class ComputerId implements Serializable {
                      @OneToOne
                      private Employee employee;
                      // 此處省略若干行
                  }
              
                  public class Computer implements Serializable {
                      @EmbeddedId
                      private ComputerId id;
                      // 此處省略若干行
                  }
              

          現(xiàn)在又出現(xiàn)了新的問題:JPA 不支持定義在嵌入式主鍵類中的關(guān)聯(lián)映射。好在天無絕人之路,EmbeddedId 的文檔中直接指出,可以使用 MapsId 注解來間接指定嵌入式主鍵類中的關(guān)聯(lián)映射,而且還附帶了一個例子!于是最終的成品就出爐了:

                  @Embeddable
                  public class ComputerId implements Serializable {
                      private String employeeId;
                      // 此處省略若干行
                  }
              
                  public class Computer implements Serializable {
                      @EmbeddedId
                      private Employee employee;
                      @MapsId("employeeId")
                      @OneToOne
                      private Employee employee;
                      // 此處省略若干行
                  }
              

          唯一的遺憾是,邏輯上的主控方 Employee 現(xiàn)在不得不成為受控方了,好在可以定義級聯(lián)操作來達到差不多的效果:

                  public class Employee implements Serializable {
                      @Id
                      private String id;
                      @OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
                      private Computer computer;
                      // 此處省略若干行
                  }
              

          雖然做到了,但確實挺繞的。希望未來版本的 JPA 能直接支持將實體類作為主鍵,樓主個人覺得不是一個技術(shù)問題。

          主站蜘蛛池模板: 武山县| 宽城| 泰安市| 灵宝市| 拜泉县| 乌鲁木齐市| 泽库县| 平陆县| 长岭县| 高安市| 江西省| 万安县| 寿阳县| 文化| 扎鲁特旗| 宣武区| 伊宁市| 韩城市| 淳化县| 黎川县| 武邑县| 雅安市| 杭锦后旗| 道孚县| 迁安市| 油尖旺区| 玉溪市| 曲阳县| 长垣县| 巴南区| 宜兴市| 方城县| 玉溪市| 若羌县| 农安县| 灌南县| 砀山县| 宁化县| 灯塔市| 土默特右旗| 如皋市|