一文帶你掌握JPA實體類注解
基本注解
@Entity
標注于實體類聲明語句之前,指出該 Java 類為實體類,將映射到指定的數(shù)據(jù)庫表。
name(可選):實體名稱。 缺省為實體類的非限定名稱。該名稱用于引用查詢中的實體。
不與 @Table 結(jié)合時,表名默認為類名的 SnakeCase(蛇形命名法),若使用name屬性,則表名為 name 值。
//以下三個類皆映射表名?student_info? @Entity?? public?class?StudentInfo{...} @Entity(name="student_info")?? public?class?StudentInfo{...} @Entity @Table(name?=?'student_info') public?class?StudentInfo{...}
@Table
當實體類與其映射的數(shù)據(jù)庫表名不同名時需要使用@Table標注說明,該標注與@Entity標注并列使用,置于實體類聲明語句之前。
- name:用于指明數(shù)據(jù)庫的表名。
- catalog、schema:用于設置表所屬的數(shù)據(jù)庫目錄或模式,通常為數(shù)據(jù)庫名。Mysql不支持catalog,schema是數(shù)據(jù)庫名。一般不需要設置。
- uniqueConstraints:用來批量命名唯一鍵,其作用等同于多個:@Column(unique = true),一般不需要設置。
@Entity @Table(name?=?"student_info",?uniqueConstraints?=?{@UniqueConstraint(columnNames?=?"class_id")}) public?class?StudentInfo?{ ????@Column(name?=?"class_id") ????private?String?classId; }
@Basic(未加注解的默認注解)
表示一個簡單的屬性到數(shù)據(jù)庫表的字段的映射,對于沒有任何注解的屬性,默認即為 @Basic 。
- fetch: 表示該屬性的讀取策略,其中 EAGER (默認)表示立即加載,LAZY 表示延遲加載。
- optional:表示該屬性是否允許為 null ,默認為 true 。
@Transient
- 表示該屬性并非一個到數(shù)據(jù)庫表的字段的映射,ORM 框架將忽略該屬性。
- 如果一個屬性并非數(shù)據(jù)庫表的字段映射,就務必將其標示為@Transient,否則,ORM框架默認其注解為@Basic 。
@Column
當實體的屬性與其映射的數(shù)據(jù)庫表的列不同名時需要使用@Column 標注說明,該注解通常置于實體的屬性前或?qū)傩缘膅etter方法之前,還可與 @Id 標注一起使用。
- name:用于設置映射數(shù)據(jù)庫表的列名。
- unique:是否是唯一標識,默認為 false(不唯一)
- nullable:否允許為 null,默認為true(null)
- insertable:表示在 ORM 框架執(zhí)行插入操作時,該字段是否應出現(xiàn) INSERT 語句中,默認為true
- updatable:表示在 ORM 框架執(zhí)行更新操作時,該字段是否應該出現(xiàn)在 UPDATE 語句中,默認為 true。對于一經(jīng)創(chuàng)建就不可以更改的字段,該屬性非常有用,如對于birthday字段。或者創(chuàng)建時間/注冊時間(可以將其設置為 false 不可修改)。
- length:數(shù)據(jù)長度,僅對String類型的字段有效,默認值255
- precision、scale:表示精度,當字段類型為double時,precision表示數(shù)值的總長度,scale表示小數(shù)點所占的位數(shù),默認值均為0。
- columnDefinition:表示該字段在數(shù)據(jù)庫中的實際類型。通常ORM框架可以根據(jù)屬性類型自動判斷數(shù)據(jù)庫中字段的類型,但是如果要將 String 類型映射到特定數(shù)據(jù)庫的 BLOB 或 TEXT 字段類型,該屬性非常有用。
@Id
用于聲明一個實體類的屬性映射為數(shù)據(jù)庫的主鍵列。
@GeneratedValue
JPA通用策略生成器,通過 strategy 屬性指定。
定義了以下幾種可供選擇的策略:
- AUTO:JPA 自動選擇合適的策略,是默認選項;
- IDENTITY:采用數(shù)據(jù)庫 ID自增長的方式來自增主鍵字段,Oracle 不支持這種方式;
- SEQUENCE:通過序列產(chǎn)生主鍵,通過 @SequenceGenerator 注解指定序列名,MySql 不支持這種方式
- TABLE:通過表產(chǎn)生主鍵,框架借由表模擬序列產(chǎn)生主鍵,使用該策略可以使應用更易于數(shù)據(jù)庫移植。該策略一般與另外一個注解一起使用@TableGenerator。
默認情況下,JPA 自動選擇一個最適合底層數(shù)據(jù)庫的主鍵生成策略:SqlServer 對應 IDENTITY,MySQL 對應 AUTO。
generator:使用指定的主鍵生成器時,這里設置為生成器名稱。
@GenericGenerator
自定義主鍵生成策略
- name:生成器名稱
- strategy:預定義的 Hibernate 策略或完全限定的類名。
@Data @Entity @Table(name?=?"student_info") public?class?StudentInfo?{ ????@Id ????@Column(name?=?"id") ????@GenericGenerator(name="idGenerator",?strategy="uuid") ????@GeneratedValue(generator?=?"idGenerator") ????private?String?id; ????@Transient ????private?String?age; ????@Column(name?=?"name") ????private?String?name; }
其他注解
@Enumerated
直接映射枚舉類型的字段。
value:
- ORDINAL:映射到數(shù)據(jù)庫字段為數(shù)字(默認)
- String:映射到數(shù)據(jù)庫字段為字符串
@Entity @Data @Table(name?=?"StudentInfo") public?class?Student?{ ????@Column ????@Enumerated ????private?Sex?sex; }
@Temporal
對于日期時間屬性映射時,可使用 @Temporal 注解來調(diào)整精度。
- DATE:日期
- TIME:時間
- TIMESTAMP:日期時間
@Data @Entity @Table(name?=?"student_info") public?class?Student?{ ????@Column ????@Temporal(TemporalType.DATE) ????private?Date?birthday; }
@DynamicInsert、@DynamicUpdate
- @DynamicInsert:設置為true,表示insert對象的時候,生成動態(tài)的insert語句,如果這個字段的值是null就不會加入到insert語句中。
- @DynamicUpdate:設置為true,表示update對象的時候,生成動態(tài)的update語句,如果這個字段的值是null就不會被加入到update語句中。
@Data @Entity @Table(name?=?"user_info") @DynamicInsert @DynamicUpdate public?class?User?{ ????@Id ????@Column(name?=?"id") ????@GenericGenerator(name="idGenerator",?strategy="uuid") ????@GeneratedValue(generator?=?"idGenerator") ????private?String?id; ????@Column(name?=?"name") ????private?String?name; ????@Basic ????private?Integer?age; ????@Column(name?=?"create_time") ????private?Long?createTime; ????@Column(name?=?"remark") ????private?String?remark; }
@Access
指定實體的訪問模式(Access mode),包括AccessType.FIELD及AccessType.PROPERTY。
- AccessType.FIELD: 字段訪問(@Column注解在屬性上),通過字段來獲取或設置實體的狀態(tài),getter和setter方法可能存在或不存在。這樣JPA默認的訪問類型為AccessType.FIELD。
- AccessType.PROPERTY: 屬性訪問(@Column注解在get方法上),持久化屬性必須有getter和setter方法,屬性的類型由getter方法的返回類型決定,同時必須與傳遞到setter方法的單個參數(shù)的類型相同。這樣JPA默認的訪問類型為AccessType.PROPERTY。
復合主鍵
@EmbeddedId + @Embeddable
當需要多個屬性作為復合主鍵時,可以把該屬性做為一個內(nèi)部類嵌套在實體類中,使用@EmbeddedId + @Embeddable實現(xiàn):
@EmbeddedId:復合主鍵
@Embeddable:注釋Java類的,表示類是嵌入類:
- 必須要實現(xiàn)Serializable接口
- 需要有無參的構造函數(shù)
//?復合主鍵類 @Data @Embeddable public?static?class?StudentId?implements?Serializable?{ ????@Column(name?=?"id") ????private?Integer?id; ????@Column(name?=?"class_id") ????private?Integer?classId; } //實體類 @Data @Entity @Table(name?=?"student_info") public?class?StudentInfo?{ ???? ????@EmbeddedId ????private?StudentId?studentId; ????@Column(name?=?"name") ????private?String?name; }
@IdClass
注解復合主鍵的類,復合主鍵類必須滿足:
- 實現(xiàn)Serializable接口;
- 有默認的public無參數(shù)的構造方法;
- 重寫equals和hashCode方法。
//?復合主鍵類 @Data @Embeddable public?static?class?StudentId?implements?Serializable?{ ????@Column(name?=?"id") ????private?Integer?id; ????@Column(name?=?"class_id") ????private?Integer?classId; } //實體類 @Data @Entity @IdClass(StudentId.class) @Table(name?=?"student_info") public?class?StudentInfo?{ ????@EmbeddedId ????private?StudentId?studentId; ????@Column(name?=?"name") ????private?String?name; }
@Embedded + @AttributeOverride
- @Embedded:注釋屬性的,表示該屬性的類是嵌入類。
- @AttributeOverrides:里面只包含了@AttributeOverride類型數(shù)組。
- @AttributeOverride:包含要覆蓋的@Embeddable類中字段名name和新增的@Column字段的屬性。
//?復合主鍵類 @Data @Embeddable public?static?class?StudentId?implements?Serializable?{ ????private?Integer?id; ????private?Integer?classId; } @Data @Entity @Table(name?=?"student_info") public?class?StudentInfo?{ ????@Embedded ????@AttributeOverrides(?{ ????????????@AttributeOverride(name?=?"id",?column?=?@Column(name?=?"id")), ????????????@AttributeOverride(name?=?"classId",?column?=?@Column(name?=?"class_id"))? ????????????}) ????private?StudentId?id; ????@Column(name?=?"name") ????private?String?name; }
實體間關聯(lián)關系
@OneToOne
實體間一對一的關系。
fetch:立即加載和延遲加載
cascade:當前類對象操作了之后,級聯(lián)對象的操作。
- REMOVE:級聯(lián)刪除操作。刪除當前實體時,與它有映射關系的實體也會跟著被刪除。
- MERGE:級聯(lián)更新(合并)操作。當前對象中的數(shù)據(jù)改變,會相應地更新級聯(lián)對象中的數(shù)據(jù)。
- DETACH:級聯(lián)脫管/游離操作。如果要刪除一個實體,但是它有外鍵無法刪除,你就需要這個級聯(lián)權限了。它會撤銷所有相關的外鍵關聯(lián)。
- REFRESH:級聯(lián)刷新操作。更新數(shù)據(jù)前先刷新對象和級聯(lián)對象,再更新。
- PERSIST:級聯(lián)持久化(保存)操作。持久保存擁有方實體時,也會持久保存該實體的所有相關數(shù)據(jù)。
- ALL,當前類增刪改查改變之后,關聯(lián)類跟著增刪改查,擁有以上所有級聯(lián)操作權
mappedBy:擁有關聯(lián)關系的域,如果關系是單向的就不需要,雙向關系表,那么擁有關系的這一方有建立、解除和更新與另一方關系的能力,而另一方?jīng)]有,只能被動管理,這 個屬性被定義在關系的被擁有方。
orphanRemoval:如果設置為true,當關系被斷開時,多方實體將被刪除。否則會將對象的引用置為null。
targetEntity:表示該屬性關聯(lián)的實體類型。該屬性通常不必指定,ORM 框架根據(jù)屬性類型自動判斷。
一對一關系的例子
people 表(id,name,sex,birthday,address_id) address 表(id,phone,zipcode,address)
People和Address是一對一的關系。
方式一:通過外鍵的方式(一個實體通過外鍵關聯(lián)到另一個實體的主鍵)
@JoinColum:保存表與表之間關系的字段,它要標注在實體屬性上。一般修飾在主控方,用來定義一對一,一對多等關系列。
關聯(lián)的實體的主鍵一般是用來做外鍵的。但如果此時不想主鍵作為外鍵,則需要設置referencedColumnName屬性。
@Entity public?class?People?{ ? ????@Id ????@Column(name?=?"id") ????@GenericGenerator(name?=?"idGenerator",?strategy?=?"uuid") ????@GeneratedValue(generator?=?"idGenerator") ????private?String?id; ? ????@Column(name?=?"name") ????private?String?name;//姓名 ? ????@Column(name?=?"sex") ????private?String?sex;//性別 ? ????@Column(name?=?"birthday") ????private?Date?birthday;//出生日期 ? ????@OneToOne(cascade=CascadeType.ALL)//People是關系的維護端,當刪除?people,會級聯(lián)刪除?address ????@JoinColumn(name?=?"address_id",?referencedColumnName?=?"id") ????private?Address?address;//地址 ? } @Entity public?class?Address?{ ????@Id ????@Column(name?=?"id") ????@GenericGenerator(name?=?"idGenerator",?strategy?=?"uuid") ????@GeneratedValue(generator?=?"idGenerator") ????private?String?id; ? ????@Column(name?=?"phone") ????private?String?phone;//手機 ? ????@Column(name?=?"zipcode") ????private?String?zipcode;//郵政編碼 ? ????@Column(name?=?"address") ????private?String?address;//地址 }
方式二:通過關聯(lián)表的方式來保存一對一的關系。
關聯(lián)表:people_address (people_id,address_id)
@JoinTable:用于構建一對多,多對多時的連接表,默認會以主控表加下劃線加反轉(zhuǎn)表為表名。
- JoinColumns:該屬性值可接受多個@JoinColumn,用于配置連接表中外鍵列的信息,這些外鍵列參照當前實體對應表的主鍵列。
- inverseJoinColumns:該屬性值可接受多個@JoinColumn,用于配置連接表中外鍵列的信息,這些外鍵列參照當前實體的關聯(lián)實體對應表的主鍵列。
@Entity public?class?People?{ ? ????@Id ????@GeneratedValue(strategy?=?GenerationType.IDENTITY) ????@Column(name?=?"id",?nullable?=?false) ????private?Long?id;//id ? ????@Column(name?=?"name") ????private?String?name;//姓名 ? ????@Column(name?=?"sex") ????private?String?sex;//性別 ? ????@Column(name?=?"birthday") ????private?Timestamp?birthday;//出生日期 ? ????@OneToOne(cascade=CascadeType.ALL)//People是關系的維護端 ????@JoinTable(name?=?"people_address", ????????????joinColumns?=?@JoinColumn(name="people_id"), ????????????inverseJoinColumns?=?@JoinColumn(name?=?"address_id")) ????private?Address?address;//地址 ? } @Entity public?class?Address?{ ????@Id ????@Column(name?=?"id") ????@GenericGenerator(name?=?"idGenerator",?strategy?=?"uuid") ????@GeneratedValue(generator?=?"idGenerator") ????private?String?id; ? ????@Column(name?=?"phone") ????private?String?phone;//手機 ? ????@Column(name?=?"zipcode") ????private?String?zipcode;//郵政編碼 ? ????@Column(name?=?"address") ????private?String?address;//地址 }
@OneToMany和@ManyToOne
注解一對多和多對一關系。
- JPA使用@OneToMany和@ManyToOne來標識一對多的雙向關聯(lián)。一端(One)使用@OneToMany,多端(Many)使用@ManyToOne。
- 在JPA規(guī)范中,一對多的雙向關系由多端(Many)來維護。就是說多端(Many)為關系維護端,負責關系的增刪改查。一端(One)則為關系被維護端,不能維護關系。
- 一端(One)使用@OneToMany注釋的mappedBy屬性表明是關系被維護端。
- 多端(Many)使用@ManyToOne和@JoinColumn來注釋屬性,@ManyToOne表明是多端,@JoinColumn設置在表中的關聯(lián)字段(外鍵)。
例子
- 文章表 article (id,title,content,author_id)
- 作者表 author (id,name)
@Entity public?class?Author?{ ? ????@Id ????@Column(name?=?"id") ????@GenericGenerator(name?=?"idGenerator",?strategy?=?"uuid") ????@GeneratedValue(generator?=?"idGenerator") ????private?String?id; ? ????@Column ????private?String?name;//姓名 ? ????//級聯(lián)保存、更新、刪除、刷新;延遲加載。當刪除用戶,會級聯(lián)刪除該用戶的所有文章 ????//擁有mappedBy注解的實體類為關系被維護端 ????//mappedBy="author"中的author是Article中的author屬性 ????@OneToMany(mappedBy?=?"author",cascade=CascadeType.ALL,fetch=FetchType.LAZY) ????private?List<Article>?articleList;//文章列表 } ? @Entity public?class?Article?{ ? ????@Id ????@Column(name?=?"id") ????@GenericGenerator(name?=?"idGenerator",?strategy?=?"uuid") ????@GeneratedValue(generator?=?"idGenerator") ????private?String?id; ? ????@Column ????private?String?title; ? ????@Lob??//?大對象,映射?MySQL?的?Long?Text?類型 ????@Basic(fetch?=?FetchType.LAZY)?//?懶加載 ????@Column(nullable?=?false)? ????private?String?content;//文章全文內(nèi)容 ? ????//可選屬性optional=false,表示author不能為空。刪除文章,不影響用戶 ????@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false) ????//設置在article表中的關聯(lián)字段(外鍵) ????@JoinColumn(name="author_id") ????private?Author?author;//所屬作者 ? }
@ManyToMany
注解多對多的關系。
角色和權限是多對多的關系。一個角色可以有多個權限,一個權限也可以被很多角色擁有。
JPA中使用@ManyToMany來注解多對多的關系,由一個關聯(lián)表來維護。這個關聯(lián)表的表名默認是:主表名+下劃線+從表名。
這個關聯(lián)表只有兩個外鍵字段,分別指向主表ID和從表ID。字段的名稱默認為:主表名+下劃線+主表中的主鍵列名,從表名+下劃線+從表中的主鍵列名。
例子
- 權限表 user_permission(id,permission_name)
- 角色表 user_role(id,department_id, create_time, description, name, update_time)
- 關聯(lián)表 user_role_permission 表(role_id, permission_id)
注意
- 多對多關系中一般不設置級聯(lián)保存、級聯(lián)刪除、級聯(lián)更新等操作。
- 本例中,由于加了@JoinTable注解,關聯(lián)關系表會按照注解指定的生成。否則去掉注解,指定Role為關系維護端,所以生成的關聯(lián)表名稱為:user_role_permission,關聯(lián)表的字段為:role_id 和permission_id。
@Data @Entity @Table(name?=?"user_permission") public?class?Permission?implements?Comparable<Permission>?{ ????@Id ????@Column(name?=?"id") ????private?String?id; ????@Column(name?=?"permission_name") ????private?String?permissionName; ????@ManyToMany(mappedBy="permissions") ????private?Set<Role>?roles; } @Data @Entity @Table(name?=?"user_role") public?class?Role?{ ????@Id ????@Column(name?=?"id") ????@GenericGenerator(name?=?"idGenerator",?strategy?=?"uuid") ????@GeneratedValue(generator?=?"idGenerator") ????private?String?id; ????@Column(name?=?"create_time") ????private?Long?createTime; ????@Column(name?=?"update_time") ????private?Long?updateTime; ????@Column(name?=?"name") ????private?String?name; ????@Column(name?=?"description") ????private?String?description; ????@Column(name?=?"department_id") ????private?String?departmentId; ????@ManyToMany(fetch?=?FetchType.EAGER,?cascade?=?CascadeType.ALL) ????@JoinTable(name?=?"user_role_permission",?joinColumns?=?{@JoinColumn(name?=?"role_id")}, ????????????inverseJoinColumns?=?{@JoinColumn(name?=?"permission_id")}) ????private?List<Permission>?permissions; }
到此這篇關于一文帶你掌握JPA實體類注解的文章就介紹到這了,更多相關JPA實體類注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java8中parallelStream性能測試及結(jié)果分析
本篇文章給大家用代碼實例做了segmentfaultjava8中parallelStream性能測試,并對測試結(jié)果做了說明,需要的朋友學習下吧。2018-01-01springboot發(fā)送request請求的方式小結(jié)
在Java中,發(fā)送HTTP請求是常見需求,hutool工具包和RestTemplate類是實現(xiàn)此功能的兩種主流方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-09-09測試springboot項目出現(xiàn)Test Ignored的解決
這篇文章主要介紹了測試springboot項目出現(xiàn)Test Ignored的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11