天天看點

JPA 關系映射(OneToOne、OneToMany、ManyToMany)

單向 OneToOne

  1. 單向一對一是關聯關系映射中最簡單的一種,簡單地說就是可以從關聯的一方去查詢另一方,卻不能反向查詢。

  1. @OneToOne注解隻用于關系的發出端,同時定義一個接收端類型的字段屬性;
  2. 單向的一對一關系在資料庫中是以外鍵的形式被映射的,

  3. 其中關系的發出端存儲一個指向關系的接收端的一個外鍵。

  4. 預設情況下這個外鍵的字段名稱,是以它指向的表的名稱加下劃線“_”加“ID”組成的。

  5. 當然我們也可以根據我們的喜好來修改這個字段,修改的辦法就是使用 @JoinColumn 這個注解

  • @OneToOne注解
  1. @Target({ElementType.METHOD, ElementType.FIELD})

  2. @Retention(RetentionPolicy.RUNTIME)

  3. public @interface OneToOne {

  4. Class targetEntity() default void.class;

  5. CascadeType[] cascade() default {};

  6. FetchType fetch() default FetchType.EAGER;

  7. boolean optional() default true;

  8. String mappedBy() default "";

  9. boolean orphanRemoval() default false;

  10. }

  1. # targetEntity屬性表示預設關聯的實體類型,預設為目前标注的實體類;

  2. # cascade屬性表示與此實體一對一關聯的實體的聯級樣式類型。聯級樣式上當對實體進行操作時的政策。

  3. 說明:在定義關系時經常會涉及是否定義Cascade(級聯處理)屬性,擔心造成負面影響.

  4. ·不定義,則對關系表不會産生任何影響

  5. ·CascadeType.PERSIST (級聯建立)

  6. ·CascadeType.REMOVE (級聯删除)

  7. ·CascadeType.REFRESH (級聯重新整理)

  8. ·CascadeType.MERGE (級聯更新)中選擇一個或多個。

  9. ·還有一個選擇是使用CascadeType.ALL ,表示選擇全部四項

  10. # fetch屬性是該實體的加載方式,有兩種:LAZY和EAGER。

  11. # optional屬性表示關聯的實體是否能夠存在null值。預設為true,表示可以存在null值。如果為false,則要同時配合使用@JoinColumn标記。

  12. # mappedBy屬性用于雙向關聯實體時,标注在不儲存關系的實體中。

  13. 在四種關聯關系

  1. 關聯指定列(@JoinColumn)

  2. # @JoinColumn用于注釋表中的字段,與@Column不同的是它要儲存表與表之間關系的字段;

  3. # name屬性是用來标記表中對應的字段的名稱。

  4. 如果不設定name的值,預設情況下,name的取值規則如下:

    name=關聯的表的名稱 + "_" + 關聯表主鍵的字段名
  5. # 預設情況下,關聯的實體的主鍵一般用來做外鍵的。如果不想用主鍵作為外鍵,則需要設定referencedColumnName屬性,

  6. 如:

    @JoinColumn(name="address_id", referencedColumnName="ref_id")
  7. # @JoinColumn可以與@OneToOne、@ManyToOne或@ManyToMany标記同時使用。

雙向 OneToOne

  1. 雙向關系有一方為關系的發出端,另一方是關系的反端,也就是“Inverse”端(接收端)。

  1. @OneToOne注解,發出端和接收端都要使用,同時定義一個接收端類型的字段屬性;

  2. 同時@OneToOne注解中的“mappedBy”屬性,這個在雙向關系的“Inverse”端是必需的

單向 OneToMany

  1. 單向關系的一對多

  2. @OneToMany 注解隻用于關系的發出端(即“一”的一方),

  3. 同時關系的發出端--定義一個集合類型的接收端的字段屬性

  1. 在一對多關聯關系映射中,預設是以中間表的方式來映射這種關系的。

  2. 中間表的名稱為關系的擁有端和 Inverse 端中間用下劃線連接配接。

  3. 中間表的字兩個字段分别為兩張表的得表名加下劃線“_”加 ID 組成。

  4. 當然我們也可以改表這種預設的中間表的映射方式,我們可以在關系的擁有端使用 @JoinClolum 來使用外鍵的方式映射這個關系。

示例

  1. 假設有兩個表,訂單表和産品表,訂單跟産品的關系是一對多的關系,那麼在JPA中怎樣表示一對多的關系呢?實體關系一對多映射有兩種方式:

  • 外鍵關聯
  1. //訂單表

  2. @Entity

  3. @Table(name = "orders")

  4. public class Order {

  5. @Id

  6. @GeneratedValue(strategy = GenerationType.AUTO)

  7. private Long id;

  8. @OneToMany(cascade = {CascadeType.ALL})

  9. @JoinColumn(name = "order_id")

  10. private List<Product> productList;

  11. ...

  12. }

  13. //産品表

  14. @Entity

  15. @Table(name = "product")

  16. public class Product {

  17. @Id

  18. @GeneratedValue(strategy = GenerationType.AUTO)

  19. private Long id;

  20. ...

  1. 這樣在表product中會增加一列order_id

  • 表關聯【預設方式】
  1. /訂單表

  2. @Entity

  3. @Table(name = "orders")

  4. public class Order {

  5. @Id

  6. @GeneratedValue(strategy = GenerationType.AUTO)

  7. private Long id;

  8. @OneToMany(cascade = {CascadeType.ALL})

  9. @JoinTable(name = "order_has_product", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")},inverseJoinColumns = {@JoinColumn(name = "product_id", referencedColumnName = "id")})

  10. private List<Product> productList;

  11. ...

  12. }

  1. joinColumns指定中間表中關聯自己ID的字段,inverseJoinColumns表示中間表中關聯對方ID的字段

  1. 這樣在product表中不會增加任何外鍵,而是建立了一張order_has_product表

雙向 OneToMany

  1. 雙向一對多關系

  2. @OneToMany(mappedBy='發出端實體名稱小寫') 注解用于關系的發出端(即“一”的一方),

  3. 同時關系的發出端--定義一個集合類型的接收端的字段屬性,

  4. @ManyToOne注解用于關系的接收端端(即“多”的一方),

  5. 同時關系的接收端--定義一個發出端的字段屬性,

單向 ManyToMany

  1. 多對多關聯關系中隻能通過中間表的方式進行映射。

  1. @ManyToMany 注解用于關系的發出端

  2. 同時關系的發出端--定義一個集合類型的接收端的字段屬性;

  3. 關系的接收端,不需要做任何定義;

雙向 ManyToMany

  1. @ManyToMany 注解用于關系的發出端和接收端

  2. 同時關系的發出端和接收端--定義一個集合類型的接收端的字段屬性;

  3. 關系的接收端,@ManyToMany(mappedBy='集合類型發出端實體的字段名稱');

參考來源:https://www.ibm.com/developerworks/cn/java/j-lo-jparelated/#icomments

繼續閱讀