SpringDataJPA在Entity中常用的注解介紹
首先我們常用的注解包括
@Entity、@Table、@Id、@IdClass、@GeneratedValue、@Basic、@Transient、@Column、@Temporal、@Enumerated、@Lob
@Entity
使用此注解定義的對象將會成為被JPA管理的實(shí)體,將映射到指定的數(shù)據(jù)庫表@Entity(name =“user”)其中name默認(rèn)是此實(shí)體類的名字,全局唯一。@Table
指定此實(shí)體類對應(yīng)的數(shù)據(jù)庫的表名。若注解不加名字則系統(tǒng)認(rèn)為表名和實(shí)體類的名字相同@Id
定義字段為數(shù)據(jù)庫的主鍵,一個實(shí)體里面必須有一個。@IdClass
利用外部類的聯(lián)合主鍵,其中外部類必須滿足一下幾點(diǎn)要求
必須實(shí)現(xiàn)Serializable接口。
必須有默認(rèn)的public無參數(shù)的構(gòu)造方法。
必須覆蓋equals和hashCode方法。equals方法用于判斷兩個對象是否相同,EntityManger通過find方法來查找Entity時是根據(jù)equals的返回值來判斷的。hashCode方法返回當(dāng)前對象的哈希碼,生成的hashCode相同的概率越小越好,算法可以進(jìn)行優(yōu)化。
@GeneratedValue
為主鍵生成策略
默認(rèn)為AUTO即JPA自動選擇合適的策略
IDENTITY
適用于MySQL,策略為自增
SEQUENCE
通過序列生成主鍵通過@SquenceGenerator指定序列名MySQL不支持
TABLE
框架由表模擬產(chǎn)生主鍵,使用該策略有利于數(shù)據(jù)庫移植
@Basic
表示此字段是映射到數(shù)據(jù)庫,如果實(shí)體字段上沒有任何注解默認(rèn)為@Basic。其中可選參數(shù)為@Basic(fetch =FetchType.LAZY, optional =false)其中fetch默認(rèn)為EAGER立即加載,LAZY為延遲加載、optional表示該字段是否可以為null@Transient
和@Basic的作用相反,表示該字段不是一個到數(shù)據(jù)庫表的字段映射,JPA映射數(shù)據(jù)庫的時候忽略此字段。@Column
定義實(shí)體內(nèi)字段對應(yīng)的數(shù)據(jù)庫中的列名
@Column(name = "real_name", unique = true, nullable = false, insertable = false, updatable = false, columnDefinition = "varchar", length = 100)
name
對應(yīng)數(shù)據(jù)庫的字段名,可選默認(rèn)字段名和實(shí)體屬性名一樣
unique
是否唯一,默認(rèn)false,可選
nullable
是否允許為空??蛇x,默認(rèn)為true
insertable
執(zhí)行insert的時候是否包含此字段??蛇x,默認(rèn)true
updatable
執(zhí)行update的時候是否包含此字段??蛇x,默認(rèn)true
columnDefinition
表示該字段在數(shù)據(jù)庫中的實(shí)際類型
length
數(shù)據(jù)庫字段的長度,可選,默認(rèn)25
@Temporal
用來設(shè)置Date類型的屬性映射到對應(yīng)精度的字段
@Temporal(TemporalType.DATE) //映射為只有日期 @Temporal(TemporalType.TIME) //映射為只有時間 @Temporal(TemporalType.TIMESTAMP) //映射為日期+時間
@Lob
將字段映射成數(shù)據(jù)庫支持的大對象類型,支持一下兩種數(shù)據(jù)庫類型的字段。(注意:Clob、Blob占用的內(nèi)存空間較大,一般配合@Basic(fetch= FetchType.LAZY)將其設(shè)置為延遲加載)
Clob
:字段類型為Character[]、char[]、String將被映射為Clob
Blob
:字段類型為Byte[]、byte[]和實(shí)現(xiàn)了Serializable接口的類型將被映射為Blob類型
接下來介紹關(guān)聯(lián)關(guān)系注解
@JoinColumn、@OneToOne、@OneToMany、@ManyToOne、@ManyToMany、@JoinTable、@OrderBy
1.@JoinColumn定義外鍵關(guān)聯(lián)字段名稱,其中屬性意義如下
name
表示目標(biāo)表的字段名,必填referencedColumnName
本實(shí)體表的字段名,非必填,默認(rèn)是本表的IDunique
外鍵字段是否唯一,可選,默認(rèn)falsenullable
外鍵字段是否允許為空,可選,默認(rèn)trueinsertable
新增操作的時候是否跟隨一起新增,可選,默認(rèn)trueupdatable
更新時候是否一起更新??蛇x,默認(rèn)true@JoinColumn
主要配合@OneToOne、@ManyToOne、@OneToMany一起使用,單獨(dú)使用沒有任何意義。@JoinColumns
定義多個字段的關(guān)聯(lián)關(guān)系
2.@OneToOne一對一關(guān)聯(lián)關(guān)系
@OneToOne(targetEntity = SysRole.class, cascade = {CascadeType.PERSIST,CascadeType.REMOVE,CascadeType.REFRESH,CascadeType.MERGE},fetch = FetchType.LAZY,optional = false,mappedBy = "userId",orphanRemoval = true)
targetEntity
非必填,默認(rèn)為該字段的類型cascade
級聯(lián)操作策略CascadeType.PERSIST級聯(lián)新建,CascadeType.REMOVE級聯(lián)刪除,CascadeType.REFRESH級聯(lián)刷新,CascadeType.MERGE級聯(lián)更新,CascadeType.ALL四項(xiàng)全選fetch
數(shù)據(jù)加載方式,默認(rèn)EAGER(立即加載),LAZY(延遲加載)optional
是否允許為空??蛇x,默認(rèn)為truemappedBy
關(guān)聯(lián)關(guān)系被誰維護(hù),非必填,一般不需要特別指定。注意:只有關(guān)系維護(hù)方才能操作兩者的關(guān)系,被維護(hù)方即使設(shè)置了維護(hù)方的屬性進(jìn)行存儲也不會更新外鍵關(guān)聯(lián)。mappedBy不能與@JoinColumn或者@JoinTable同時使用。mappedBy的值指的是另一方的實(shí)體里面屬性的字段,而不是數(shù)據(jù)庫字段,也不是實(shí)體對象的名字,即另一方配置了@JoinColumn或者@JoinTable注解的屬性的字段名稱orphanRemoval
是否級聯(lián)刪除,和CascadeType.REMOVE效果一樣,兩種只要配置一種就會自動級聯(lián)刪除@OneToOne
需要配合@JoinColumn一起使用,可以雙向關(guān)聯(lián),也可以只配置一方。下面我們舉一個例子:假設(shè)一個用戶只擁有一個角色SysUser如下
@OneToOne @JoinColumn(name = "role_id",referencedColumnName = "user_id") private SysRole role; //若需要雙向關(guān)聯(lián)則SysRole的內(nèi)容如下 @OneToOne(mappedBy = "role") private SysUser user; //當(dāng)然也可以不用選擇mappedBy,使用下面效果也一樣 @OneToOne @JoinColumn(name = "user_id",referencedColumnName = "role_id") private SysUser user;
3.@OneToMany和@ManyToOne一對多和多對一的關(guān)聯(lián)關(guān)系
@Entity @Table(name="user") class User implements Serializable{ private Long userId; @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy = "user") private Set<Role> setRole; } @Entity @Table(name="role") class Role{ private Long roleId; @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER) @JoinColumn(name = "user_id")//user_id字段作為外鍵 private User user; }
4.@OrderBy關(guān)聯(lián)查詢的時候排序,一般和@OneToMany一起使用
@Entity @Table(name="user") class User implements Serializable{ private Long userId; @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy = "user") @OrderBy("role_name DESC") private Set<Role> setRole; }
5.@JoinTable關(guān)聯(lián)關(guān)系表一般和@ManyToMany一起使用
@ManyToMany表示多對多,也有單雙向之分,單雙向和注解無關(guān),只看實(shí)體類之間是否相互引用
@JoinTable(name = "sys_user_role", joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}) @ManyToMany(cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER) private List<SysRole> roles;
@JoinTable
中name表示中間關(guān)聯(lián)關(guān)系表名@JoinTable
中的joinColumns表示主鏈接表的字段,即當(dāng)前對象內(nèi)對應(yīng)的連接字段@JoinTable
中inverseJoinColumns表示被連接的表的外鍵字段
6.Left Join、Inner join和@EntityGraph
當(dāng)使用@ManyToMany、@ManytoOne、@OneToMany、@OneToOne關(guān)聯(lián)關(guān)系的時候SQL執(zhí)行查詢的時候總是一條主查詢語句和N條子查詢語句組成,運(yùn)行的效率較地下,如果子對象有N個就會執(zhí)行N+1條SQL,JPA2.1推出的@EntityGraph、@NamedEntityGraph用來提高查詢效率@NamedEntityGraph配置在@Entity上面,而@EntityGraph配置在Repository的查詢方法上面
@NamedEntityGraph(name = "User.addressEntityList",attributeNodes = {@NamedAttributeNode("setRole"),@NamedAttributeNode("dept")}) @Entity @Table(name="user") public class User implements Serializable{ private Long userId; @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY,mappedBy = "user") @OrderBy("role_name DESC") private Set<Role> setRole; @OneToOne @JoinColumn(name = "dept_id",referencedColumnName = "user_id") private Department dept; }
然后只需要在Repository查詢方法上面加上@EntityGraph注解即可,其中value就是@NamedEntityGraph中的Name,配置如下
@EntityGraph(value ="User.addressEntityList") List<User> findAll();
對于關(guān)系查詢需要注意以下事項(xiàng):
- 所有的注解要么全部配置在字段上,要么全部配置在get方法上面,不能混用,混用項(xiàng)目就會啟動不起來
- 所有關(guān)聯(lián)都支持單雙向關(guān)聯(lián)。當(dāng)JSON序列化的時候使用雙向注解會產(chǎn)生死循環(huán),需要人為手動轉(zhuǎn)換一次,或者使用@JsonIgnore
- 所有的關(guān)聯(lián)表一般不需要建立外鍵索引
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring初始化源碼之關(guān)鍵類和擴(kuò)展接口詳解
Spring就是一個大工廠,可以將所有對象的創(chuàng)建和依賴關(guān)系的維護(hù)交給Spring管理,下面這篇文章主要給大家介紹了關(guān)于spring初始化源碼之關(guān)鍵類和擴(kuò)展接口的相關(guān)資料,需要的朋友可以參考下2023-04-04Maven項(xiàng)目分析剔除無用jar引用的方法步驟
這篇文章主要介紹了Maven項(xiàng)目分析剔除無用jar引用的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10idea中開啟Run Dashboard 和 快速復(fù)制項(xiàng)目并改變端口的方法
這篇文章主要介紹了idea中開啟Run Dashboard 和 快速復(fù)制項(xiàng)目并改變端口的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08JAVA如何把數(shù)據(jù)庫的數(shù)據(jù)處理成樹形結(jié)構(gòu)
本文介紹了JAVA如何把數(shù)據(jù)庫的數(shù)據(jù)處理成樹形結(jié)構(gòu),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09Mybatis中where標(biāo)簽與if標(biāo)簽結(jié)合使用詳細(xì)說明
mybatis中if和where用于動態(tài)sql的條件拼接,在查詢語句中如果缺失某個條件,通過if和where標(biāo)簽可以動態(tài)的改變查詢條件,下面這篇文章主要給大家介紹了關(guān)于Mybatis中where標(biāo)簽與if標(biāo)簽結(jié)合使用的詳細(xì)說明,需要的朋友可以參考下2023-03-03java如何讀取properties文件將參數(shù)值配置到靜態(tài)變量
這篇文章主要介紹了java如何讀取properties文件將參數(shù)值配置到靜態(tài)變量問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08Mybatis mapper標(biāo)簽中配置子標(biāo)簽package的坑及解決
這篇文章主要介紹了Mybatis mapper標(biāo)簽中配置子標(biāo)簽package的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09