關(guān)系型數(shù)據(jù)庫(kù)
關(guān)系數(shù)據(jù)庫(kù)衔掸,是建立在關(guān)系模型基礎(chǔ)上的數(shù)據(jù)庫(kù)烫幕,借助于集合代數(shù)等數(shù)學(xué)概念和方法來處理數(shù)據(jù)庫(kù)中的數(shù)據(jù)。現(xiàn)實(shí)世界中的各種實(shí)體以及實(shí)體之間的各種聯(lián)系均用關(guān)系模型來表示敞映。關(guān)系模型是由埃德加·科德于1970年首先提出的较曼,并配合“科德十二定律”。現(xiàn)如今雖然對(duì)此模型有一些批評(píng)意見振愿,但它還是數(shù)據(jù)存儲(chǔ)的傳統(tǒng)標(biāo)準(zhǔn)捷犹。標(biāo)準(zhǔn)數(shù)據(jù)查詢語言SQL就是一種基于關(guān)系數(shù)據(jù)庫(kù)的語言,這種語言執(zhí)行對(duì)關(guān)系數(shù)據(jù)庫(kù)中數(shù)據(jù)的檢索和操作冕末。 關(guān)系模型由關(guān)系數(shù)據(jù)結(jié)構(gòu)萍歉、關(guān)系操作集合、關(guān)系完整性約束三部分組成档桃。
簡(jiǎn)單說翠桦,關(guān)系型數(shù)據(jù)庫(kù)是由多張能互相聯(lián)接的二維行列表格組成的數(shù)據(jù)庫(kù)。
一對(duì)一關(guān)系處理
one class
package com.example.demo.entity.onetoone; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToOne; import lombok.Getter; import lombok.Setter; @Entity @Getter @Setter public class One { @Id @GeneratedValue private String id; private String name; @OneToOne private Two two; }
two class
@Entity @Getter @Setter public class Two { @Id @GeneratedValue private String id; private String name; }
默認(rèn)建表結(jié)構(gòu)
一對(duì)一
一對(duì)一
如果我們只是單純的在兩個(gè)實(shí)體類中分別加上@OneToOne注解,會(huì)發(fā)現(xiàn)兩張表都分別引入了對(duì)方的主鍵作為外鍵销凑。明顯的數(shù)據(jù)冗余丛晌,畢竟關(guān)系不用雙方存儲(chǔ)。
利用mappedBy屬性斗幼,指明關(guān)系由哪一方維護(hù)澎蛛。
一對(duì)多關(guān)系處理
創(chuàng)建兩個(gè)實(shí)體對(duì)象,分別對(duì)應(yīng)一與多的一方蜕窿。
情況1-只在多的一方在@ManyToOne注解one方
package com.example.demo.entity.onetomany; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import lombok.Getter; import lombok.Setter; @Entity @Getter @Setter public class OneObject { @Id @GeneratedValue private String id; private String name; }
many方
package com.example.demo.entity.onetomany; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; import lombok.Getter; import lombok.Setter; @Entity @Getter @Setter public class ManyObject { @Id @GeneratedValue private String id; private String name; @ManyToOne private OneObject object; }
此時(shí)我只在多的一方加了一個(gè)ManyToOne注解谋逻。生成表結(jié)構(gòu)關(guān)系如下
只有ManyToOne一個(gè)注解
默認(rèn)是在many_object里面加了一個(gè)外鍵列
只有ManyToOne列屬性
情況2-只在one的一方加
只有一個(gè)OneToMany注解
默認(rèn)情況下是生成了一張關(guān)系表。用戶維護(hù)一對(duì)多關(guān)系桐经。
關(guān)系表
至于默認(rèn)的表名列名毁兆,大家可以去看生成規(guī)則。不在這篇文章研究范圍阴挣。
情況3-不想生成關(guān)系表气堕,想通過列名維護(hù)。
此時(shí)使用@JoinColumn屬性畔咧。
one方@OneToMany @JoinColumn(name="obj_id") private List<ManyObject> manyObject;
many方
@ManyToOne(fetch=FetchType.EAGER,cascade=CascadeType.ALL) @JoinColumn(name="obj_id") private OneObject object;
加上@JoinColumn屬性表結(jié)構(gòu)
擴(kuò)展
在一對(duì)多雙方都設(shè)置了關(guān)聯(lián)關(guān)系后茎芭,進(jìn)行數(shù)據(jù)存儲(chǔ)模擬
@Test public void contextLoads() { OneObject object = new OneObject("1"); object.setManyObject(new ArrayList<ManyObject>()); ManyObject manyObject = new ManyObject("ysh"); ManyObject manyObject2 = new ManyObject("ysh2"); object.getManyObject().add(manyObject); object.getManyObject().add(manyObject2); mp.save(manyObject); mp.save(manyObject2); op.save(object); }
控制端打印sql如下
除了三條insert數(shù)據(jù)。還有兩條update語句誓沸。這個(gè)很好理解梅桩。先插入多的一方數(shù)據(jù),然后在把one對(duì)應(yīng)的一方關(guān)聯(lián)加進(jìn)去拜隧。
想要避免這種多余sql宿百。有兩種方式。
方法一:直接把one對(duì)應(yīng)的一方賦值給多的一方洪添。(上面是把多的一方賦值給one的一方)public void contextLoads() { OneObject object = new OneObject("1"); object.setManyObject(new ArrayList<ManyObject>()); ManyObject manyObject = new ManyObject("ysh"); ManyObject manyObject2 = new ManyObject("ysh2"); manyObject.setObject(object); manyObject2.setObject(object); // object.getManyObject().add(manyObject); // object.getManyObject().add(manyObject2); op.save(object); mp.save(manyObject); mp.save(manyObject2); }
控制臺(tái)日志
可以看到update語句已經(jīng)沒有了犀呼。
方法二:利用OneToMany注解里面的mappedBy屬性@OneToMany(mappedBy = "object") // @OneToMany // @JoinColumn(name="obj_id") private List<ManyObject> manyObject;
注意mappedBy不能與@JoinColumn注解連用
利用mappedBy屬性后的輸出
可以看到也實(shí)現(xiàn)了減少兩條sql的功能。算是小功能優(yōu)化薇组。
多對(duì)多
正常建立兩個(gè)多對(duì)多關(guān)系實(shí)體
1.多對(duì)多實(shí)體一package com.example.demo.entity.manytomany; import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import lombok.Getter; import lombok.Setter; @Getter @Setter @Entity public class Manyone { @Id @GeneratedValue private Long id; private String name; @ManyToMany private List<Manytwo> manytwos; }
多對(duì)多實(shí)體二
package com.example.demo.entity.manytomany; import java.util.List; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import lombok.Getter; import lombok.Setter; @Getter @Setter @Entity public class Manytwo { @Id @GeneratedValue private Long id; private String name; @ManyToMany private List<Manyone> manyones; }
表結(jié)構(gòu)
很顯然的關(guān)系表冗余。
利用@ManyToMany(mappedBy="manytwos")的mappedBy屬性將關(guān)系表改為由一端維護(hù)坐儿。生成表結(jié)構(gòu)如下:
表結(jié)構(gòu)
cascade屬性
public enum CascadeType { /** Cascade all operations */ ALL, /** Cascade persist operation */ PERSIST, /** Cascade merge operation */ MERGE, /** Cascade remove operation */ REMOVE, /** Cascade refresh operation */ REFRESH, /** * Cascade detach operation * * @since Java Persistence 2.0 * */ DETACH }
fetch屬性
FetchType.LAZY:懶加載律胀,加載一個(gè)實(shí)體時(shí),定義懶加載的屬性不會(huì)馬上從數(shù)據(jù)庫(kù)中加載貌矿。
FetchType.EAGER:急加載炭菌,加載一個(gè)實(shí)體時(shí),定義急加載的屬性會(huì)立即從數(shù)據(jù)庫(kù)中加載逛漫。
結(jié)語
本文屬于基礎(chǔ)篇黑低。覺得不錯(cuò)也可以點(diǎn)亮下方小星星。