學習Spring-Data-Jpa(五)---可嵌入對象和元素集合的使用


1、場景一:地址信息(省、市、縣、詳細地址)在很多實體中都需要,比如說作者有地址,訂單也有地址,但是他們的地址並不能獨立與他們存在,所以地址不能映射為實體,
那么我們就需要在作者實體和訂單實體中都添加這些地址信息。這時如果我們想要在地址信息中添加一個郵編,就需要在每一個用到地址的實體中都添加郵編字段,很是繁
瑣。面向對象編程的做法是,我們將地址信息封裝到一個對象中,然后需要地址信息的實體如引用這個對象。直接這樣做的話,如果地址類不實現Serializable接口,啟動
報錯,實現了后,會把地址對象映射為二進制的數據庫tinyblob字段,這顯然不是我們想要的,什么好辦法進行處理呢?

JPA為我們提供了一組注解,來解決這個問題,@Embeddable/@Embedded。
@Embeddable:指定一個類,該類的實例存儲為所屬實體的固有部分並共享該實體的標識。嵌入對象的每個持久屬性或字段都映射到實體的數據庫表。
@Embedded:指定其值為可嵌入類的實例的實體的持久字段或屬性。可嵌入類必須被注釋為可嵌入的。

在被@Embeddable標記的可嵌入類中的字段,也可以使用JPA的注解來進行設置。
可以通過 @AttributeOverrides和@AttributeOverride來修改@Embedded標記的嵌入對象字段在本實體表中的映射字段名稱,修改后原有可嵌入對象中的字段設置失效。
多重嵌套用"."進行連接。

注意:被引用對象和引用對象具有相同的生命周期時,才考慮使用內嵌對象。

可嵌入地址類:
/**
 *  地址對象
 *
 * @author caofanqi
 */
@Data
@Builder
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class Address {

    private String province;

    private String city;

    private String county;

    /**
     * 可嵌入對象中的字段也可以使用@Column進行修飾
     */
    @Column(nullable = false)
    private String detailedAddress;

    private String zipCode;

}

作者實體中:

/**
 * 作者實體
 *
 * @author caofanqi
 */
@Data
@Entity
@Builder
@Table(name = "jpa_author")
@NoArgsConstructor
@AllArgsConstructor
public class Author {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String authorName;


    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "detailedAddress",column = @Column(name = "addr_detailed")),
            @AttributeOverride(name = "zipCode",column = @Column(name = "addr_zip"))
    })
    private Address address;

}


2、場景二:作者有多個昵稱我們要怎么映射呢?
JPA為我們提供了@ElementCollection,指定基本類型或可嵌入類的實例集合。如果要通過集合表映射集合,則必須指定。
屬性 targetClass:集合指定了泛型可選,否者必須指定。必須是基本類型或可嵌入類型。
屬性 fetch:數據抓取策略。默認延遲加載。
會為我們創建一張中間表,默認命名主實體 + "_" + 集合屬性名稱,默認外鍵名稱,主實體類名 + "_" + 主實體主鍵。

如果我們想要進行修改設置,可以使用@CollectionTable注解進行設置。

注意,一般我們會直接在主實體中使用一個字段進行存放,存取的時候自己做一下處理(比如說逗號隔開的字符串),這樣就不用多產生一張表了。

作者實體中:
/**
 * 作者實體
 *
 * @author caofanqi
 */
@Data
@Entity
@Builder
@Table(name = "jpa_author")
@NoArgsConstructor
@AllArgsConstructor
public class Author {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String authorName;


    /**
     *  @ElementCollection 映射基本類型和可嵌入類型集合,可以使用@CollectionTable 指定額外產生表的名稱,外鍵名稱等。
     */
    @ElementCollection
    @CollectionTable(name = "jpa_author_nick",joinColumns = {@JoinColumn(name = "a_id",referencedColumnName = "id")})
    private Set<String> nickName;

}


3、場景三:如果作者有多個地址呢,比如說家庭地址,工作地址等,我們應該怎么辦呢?
我們可以將上面兩種場景結合起來使用,將可嵌入的地址對象放到一個Map<String,Address> 中,這樣生成的集合表就會將
主實體id和map的key作為集合表的聯合主鍵。
同樣我們可以使用@CollectionTable對集合表進行設置,使用@AttributeOverrides和@AttributeOverride設置數據庫字段名稱,
只不過要添加前綴value.。
可以使用@MapKeyColumn指定map的key在集合表中的列名,和其他一些設置,同@Column。默認列名是屬性字段 + "_key"。

作者實體:
/**
 * 作者實體
 *
 * @author caofanqi
 */
@Data
@Entity
@Builder
@Table(name = "jpa_author")
@NoArgsConstructor
@AllArgsConstructor
public class Author {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String authorName;

    /**
     * 一個作者有多個地址
     */
    @ElementCollection
    @MapKeyColumn(name = "addr_key")
    @CollectionTable(name = "jpa_author_address")
    @AttributeOverrides({
            @AttributeOverride(name = "value.detailedAddress",column = @Column(name = "addr_detailed")),
            @AttributeOverride(name = "value.zipCode",column = @Column(name = "addr_zip"))
    })

    private Map<String,Address> addresses;

}

  對應生成的表

    

 

    

 

 

源碼地址:https://github.com/caofanqi/study-spring-data-jpa

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM