JPA 內嵌對象

問題描述

有些場景下,有些關係不足以拆分出一個實體,可是若是新建一個對象管理會讓代碼更清晰,這種場景下用到了內嵌對象。html

clipboard.png

一個Teacher,三個屬性,idfirstNamelastNamejava

咱們能夠直接這麼寫,也能夠建一個內嵌的Name對象,雖然在一個實體中差異不大,可是若是之後有用到name的場景,能夠直接使用該內嵌對象。app

解決方案

實現

如下代碼省略setget方法:編碼

@Entity
public class Teacher {

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

    private Name name;
}
@Embeddable
public class Name {

    private String firstName;

    private String lastName;
}

啓動程序,生成的表結構以下:spa

clipboard.png

因此,映射時直接將內嵌對象中的字段添加到該實體中,而後映射到數據表。hibernate

思考

其實說白了就是許多的實體中都有這幾個屬性,可是根據邏輯關係或複雜度來講不足以單獨創建一個實體,因此使用內嵌對象。設計

就像項目中的不肯定度與測量範圍同樣,雖然屬性很多,不足以單獨抽出一個實體,可是又有不少實體去用。code

根據內嵌的原理,咱們能夠推斷,使用內嵌對象的實體與內嵌對象是一對一的關係時,確定是能夠映射的?那若是映射一個List呢?由於實際業務場景是不許確度,以前都是一對一使用的該內嵌對象,而後需求變更,須要一對多實現。orm

嘗試多關聯

抱着懷疑的態度,咱們嘗試一下。htm

@Entity
public class Teacher {

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

    private List<Name> names = new ArrayList<>();
}

運行程序,果真報錯,應該是咱們映射的方式有問題,去查查官方文檔。

clipboard.png

官方文檔

官方文檔天然是萬能的:Collection Mapping - Hibernate

clipboard.png

Using annotations you can map Collections, Lists, Maps and Sets of associated entities using @OneToMany and @ManyToMany. For collections of a basic or embeddable type use @ElementCollection.
使用註解映射`Collection`、`List`、`Map`、`Set`,實體使用`@OneToMany`與`@ManyToMany`,基本類型或內嵌類型使用`@ElementCollection`。
@Entity
public class Teacher {

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

    @ElementCollection
    private List<Name> names = new ArrayList<>();
}

運行程序,查看生成的表結構:

clipboard.png

teacher表:

clipboard.png

teacher_names表:

clipboard.png

看着彷佛沒什麼問題,可是設計表會發現teacher_names是有貓膩的。

clipboard.png

內嵌對象集合映射的表沒有主鍵!固然,若是僅僅從teacher這方面看,這麼設計是很合理的。可是並不能知足咱們的需求。

思考

StackOverflow回答的很是好。

clipboard.png

內嵌對象沒有id,若是需求複雜,仍是用實體吧!內嵌對象只適用於該對象十分簡單的狀況。

兼容原內嵌

因此,如今的需求變成了原內嵌對象不能動,好多實體用到了,而後又須要將內嵌對象變爲實體。原問題就是由於內嵌對象沒有id形成的,填個id就行了。

@Entity
public class SuperName {

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

    private Name name;

    @ManyToOne
    private Teacher teacher;
}
@Entity
public class Teacher {

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

    @OneToMany(mappedBy = "teacher")
    private List<SuperName> superNames = new ArrayList<>();
}

再看錶結構,沒毛病!

clipboard.png

clipboard.png

總結

用一個新的註解或編碼方式時,首要任務是新建一個項目,而後去各類嘗試學會它的應用場景,看別人的博客永遠沒有本身嘗試一遍理會的透徹。

只要沒有被官方棄用的東西,都有其存在的價值,只是應用場景不一樣而已,永遠沒有無用的東西,僅僅是由於咱們還沒發現。

相關文章
相關標籤/搜索