1.spring data jpa的映射關系
















當要進行測試用例的時候,就從有注解@SpringBootApplication的類BookShopApplication做入口,把整個spring容器組裝起來,然后拿需要的bean,然后測試里面的代碼
@Transactional就是說所有的測試用例都要在事務下面執行,頁就是說在測試用例完了的時候,所有的數據庫操作都會回滾,不會執行真正的數據庫操作,然后就能保證反復的執行測試用例了
注意:所有的測試用例都應該是:public void   (即:沒有返回值)

@Entit y就是把這個bean映射到數據庫中去
@id是不敖明這個屬性是主鍵
@GeneratedValue指定當前主鍵的生成策略
@table(name="roncoo_category")是將實體類映射到數據庫中后命名表名為roncoo_category

意思是將name映射到數據庫中的字段名命名為roncoo
新建一個命名策略
用來生成表名和字段名的前綴
發現bean中的string類型屬性的會自動在數據庫中轉化成varchar類型的字段
long類型會自動轉成bigint
date類型會自動轉成datetime
意思是將date類型的屬性轉成date,不適用默認的datatime

意思是用枚舉類作為屬性進行映射,最終到數據庫中映射成varchar
內嵌對象的映射
@Embeddable 意思是說這是一個可嵌入的對象(可注入)
(可被注入)

這個就叫做內嵌對象的映射,我們可以在任何一個需要地址信息的類中嵌入address,

集合映射
如何映射集合?
如下例子


,執行后,發現多出來一張表
這兩個表形成了一對多的關系,而生成的hobbies表中有兩個字段,一個是Author的id,還有一個是hobbies字段




單向多對一映射
圖書和category是多對一的關系,多本書可以屬於一個門類,所以用@manyToOne
這本書是屬於哪個門類的

category_id是一個外鍵,指向 category表的主鍵,就產生了一個主外鍵關系

因為是單向的,所以只能通過book訪問到category,而不能通過category門類訪問到門類下面有哪些book的,這個叫做單向多對一的關系
單向一對多的關系
這個是要建立在Category里面的,Category和book是一對多的關系,一個門類里面可以有多個book



這個因為是單向一對多,通過門類可以訪問門類下的book,但是從圖書book是訪問不到Category門類的
維護方是在一的一方,而不是在多的那邊,當一對多是在一的一方維護的時候,他是用一張新的表來維護這個關系的;
而在維護一對多,是在多的一方維護的話,就會在多的一方產生一個外鍵來指向一個一方的主鍵

所以標准的應該是: 在維護一對多,在多的一方用產生外鍵來維護,而不是在一的一方用產生一張新表的方式來維護,

一般情況下是不太建議使用單向一對多關系,但是如果非要建立單向一對多關系 ,應該在多的一方使用@ManyToOne,而不是在一的一方使用@OneToMany


但是最佳實踐是建立一個雙向關系


在多的一方使用@ManyToOne,並且在一的一方使用@OneToMany,
當拿到book對象的時候,能通過book中的category的getCategory()拿取到一的一方 category的門類的信息
當拿到門類信息category的時候,通過getBooks()拿到門類下的所有圖書book的信息
當有一對多或多對一的關系的時候比如:在數據庫中查出一個book對象來的時候,他會用一個select語句從book表中查出一條記錄來把他轉成一個book對象,當在調book對象的getCategory()方法的時候,他會立刻執行一條sql,把相應的門類信息查出來,放到這
同樣的,當查Category,掉Category對象的getBook()方法,也會執行一條SQL,把門類下的所有book讀出來,放到

因為加了@ManyToOne和@OneToMany,所以兩邊都在維護這個關系,在 @OneToMany這邊維護的時候,還是建了多余的這張表,現在的需求就是希望在多的一方book對象中通過產生外鍵來維護,一的一方仍然聲明@OneToMany,通過Category可以訪問下面的books,希望是一個雙向關聯

一對多的關系不由一的這一端來維護,而交給多的那一端,也就是book里面的Category屬性來維護,即 @ManyToOne生成外鍵的屬性,做了這個設置之后Category就放棄了一對多的這樣一個管理,不會再生成那張多余的表,只是有多的這端,也就是Book這端生成一個外鍵來維護這個關系


@OneToMany(@mappedBy="category")的意思是放棄去管理一對多的關系(即:不多生成一張表,只提供能從一的一方查到多的一方這種能力),只在多的一端去管理

下面介紹幾個@ManyToOne常用的屬性:


fetch是實體的加載方式,有兩個值,一個是eager,還有一個是lazy,
lazy就是在讀取book 信息的時候,不執行一個關聯查詢,不去查門類Category信息;
eager是讀取book信息的時候(讀取book的SQL是一個關聯查詢,會關聯到Category表上去) ,同時把門類的信息查出來
不關聯到另一個表查詢的是lazy,關聯到另一個表查的是eager

當用 eager這種策略的時候,當查出一個book的時候,Category對象里面的屬性都已經被填充好了,因為他已經將數據從category表中查出來了
而當使用lazy這個策略查一個book的時候,Category中是沒有相應的信息的,當用getCategory()去get某一個屬性的時候他才又執行一個select,把Category的信息查出來
注意在 @ManyToOne中默認的抓取策略是eager,不寫的時候,查book默認的是把Category的信息也帶出來
可以控制相關策略的抓取控制

optional是用來標識category這個外鍵字段是否可以為空,默認是true,可以為空,即書可以不屬於任何一個門類
如果改成false就是說book必須有一個門類,不能存在某有門類的book
cascade這是表示與實體關聯的那些實體的級聯處理的類型,默認情況下在@ManyToOne這一端是不會設這個類型的

下面介紹幾個 @OneToMany 常用的屬性

其中也有fetch=fetchType.lazy和 fetch=fetchType.eager屬性外,還多出了orphanRemoval屬性
orphanRemoval:
orphanRemoval用來表示當前指定集合中的一個元素被從集合中移除后是否從數據庫中刪除,即:假如book中有5本書,然后用list的remove方法(例如:books.remove(1) ),把一本書挪出去了,只是把他從集合中去掉了,從集合中去掉以后這個Book就不屬於任何一個門類了,那么 是不是把這本書刪掉,就是由orphanRemoval控制的,當等於orphanRemoval=true時,當把那本書從集合中移除掉,這本書會自動被刪掉,默認的是false
cascade=CascadeType.REMOVE這是一個級聯的操作,當刪除一個Category的時候,把這個門類下所對應的所有圖書,一塊刪掉。
默認情況下,這個屬性是空的什么都不做的,也就是說把門類刪掉,不會影響里面的書,刪的時候會報錯的,因為有外鍵了

多對多關系的映射
在這個案例里面,圖書和作者是多對多關系,一個作者可以寫多本書,一本書可以有多個作者
創建了一個中間對象BookAuthor,用來保存多對多關系,在這個 對象中 有一個指向book的引用還有一個指向作者author的引用 

想要知道這個作者寫了哪些書,不是直接指向book的(直接指向book就變成了,一對多關系了),
而要指向的這個中間對象 BookAuthor,由BookAuthor對象中的author屬性來管理   一對多的關系
同樣在book中也要寫上面的這個屬性
意思是說這個book是由哪些作者寫成的,同樣也指向BookAuthor這個中間對象,告訴book對象,是靠 BookAuthor中的
book屬性來維護這個一對多關系的

在bookauthor對象中存了多對多的關系

在多對多關系中,為什么不用@ManyToMany呢,因為spring官方建議將多對多關系最好拆成兩個一對多關系
注意:
這個注解的作用是,當通過作者的一個getbooks方法拿取作者寫額所有的書的時候,這些書就會按照書名升序排列
一對一關系的映射
比如說用戶表可能有30個字段,但是這些字段中只有10個字段是比較常用的,有些就不常用,如果把這所有的字段放到一個表中去,然后每次查表都會查許多字段,所以一般就會將一張表拆成兩張表,一個表放常用的,另一個表放不常用的

authorInfo不去管理一對一的關系,而將管理權交到Author這個對象的Info屬性上(即交到會去建外鍵的屬性上),但是可以由 authorInfo表查到author表這一方

注意:在一對多的關系中,一的一方維護權是用建表的方式完成的(是不建議的),
           多的一方的維護權是通過生成外鍵的方式完成的(建議)。







免責聲明!

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



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