掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
哈嘍,大家好,我是指北君。

創(chuàng)新互聯(lián)長期為上千客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為晉中企業(yè)提供專業(yè)的網(wǎng)站建設(shè)、做網(wǎng)站,晉中網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
今天給大家介紹一下 JPA 實(shí)體類中的注解,希望能對(duì)大家有幫助。
標(biāo)注于實(shí)體類聲明語句之前,指出該 Java 類為實(shí)體類,將映射到指定的數(shù)據(jù)庫表。
不與 @Table 結(jié)合時(shí),表名默認(rèn)為類名的 SnakeCase(蛇形命名法),若使用name屬性,則表名為 name 值。
//以下三個(gè)類皆映射表名 student_info
@Entity
public class StudentInfo{...}
@Entity(name="student_info")
public class StudentInfo{...}
@Entity
@Table(name = 'student_info')
public class StudentInfo{...}
當(dāng)實(shí)體類與其映射的數(shù)據(jù)庫表名不同名時(shí)需要使用@Table標(biāo)注說明,該標(biāo)注與@Entity標(biāo)注并列使用,置于實(shí)體類聲明語句之前。
@Entity
@Table(name = "student_info", uniqueConstraints = {@UniqueConstraint(columnNames = "class_id")})
public class StudentInfo {
@Column(name = "class_id")
private String classId;
}
表示一個(gè)簡單的屬性到數(shù)據(jù)庫表的字段的映射,對(duì)于沒有任何注解的屬性,默認(rèn)即為 @Basic 。
表示該屬性并非一個(gè)到數(shù)據(jù)庫表的字段的映射,ORM 框架將忽略該屬性。
如果一個(gè)屬性并非數(shù)據(jù)庫表的字段映射,就務(wù)必將其標(biāo)示為@Transient,否則,ORM框架默認(rèn)其注解為@Basic 。
當(dāng)實(shí)體的屬性與其映射的數(shù)據(jù)庫表的列不同名時(shí)需要使用@Column 標(biāo)注說明,該注解通常置于實(shí)體的屬性前或?qū)傩缘膅etter方法之前,還可與 @Id 標(biāo)注一起使用。
用于聲明一個(gè)實(shí)體類的屬性映射為數(shù)據(jù)庫的主鍵列。
AUTO:JPA 自動(dòng)選擇合適的策略,是默認(rèn)選項(xiàng);
IDENTITY:采用數(shù)據(jù)庫 ID自增長的方式來自增主鍵字段,Oracle 不支持這種方式;
SEQUENCE:通過序列產(chǎn)生主鍵,通過 @SequenceGenerator 注解指定序列名,MySql 不支持這種方式
TABLE:通過表產(chǎn)生主鍵,框架借由表模擬序列產(chǎn)生主鍵,使用該策略可以使應(yīng)用更易于數(shù)據(jù)庫移植。該策略一般與另外一個(gè)注解一起使用@TableGenerator。
自定義主鍵生成策略
@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;
}
直接映射枚舉類型的字段。
ORDINAL:映射到數(shù)據(jù)庫字段為數(shù)字(默認(rèn))
String:映射到數(shù)據(jù)庫字段為字符串
@Entity
@Data
@Table(name = "StudentInfo")
public class Student {
@Column
@Enumerated
private Sex sex;
}
對(duì)于日期時(shí)間屬性映射時(shí),可使用 @Temporal 注解來調(diào)整精度。
@Data
@Entity
@Table(name = "student_info")
public class Student {
@Column
@Temporal(TemporalType.DATE)
private Date birthday;
}
@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;
}
指定實(shí)體的訪問模式(Access mode),包括AccessType.FIELD及AccessType.PROPERTY。
@EmbeddedId + @Embeddable
當(dāng)需要多個(gè)屬性作為復(fù)合主鍵時(shí),可以把該屬性做為一個(gè)內(nèi)部類嵌套在實(shí)體類中,使用@EmbeddedId + @Embeddable實(shí)現(xiàn):
必須要實(shí)現(xiàn)Serializable接口
需要有無參的構(gòu)造函數(shù)
// 復(fù)合主鍵類
@Data
@Embeddable
public static class StudentId implements Serializable {
@Column(name = "id")
private Integer id;
@Column(name = "class_id")
private Integer classId;
}
//實(shí)體類
@Data
@Entity
@Table(name = "student_info")
public class StudentInfo {
@EmbeddedId
private StudentId studentId;
@Column(name = "name")
private String name;
}
注解復(fù)合主鍵的類,復(fù)合主鍵類必須滿足:
// 復(fù)合主鍵類
@Data
@Embeddable
public static class StudentId implements Serializable {
@Column(name = "id")
private Integer id;
@Column(name = "class_id")
private Integer classId;
}
//實(shí)體類
@Data
@Entity
@IdClass(StudentId.class)
@Table(name = "student_info")
public class StudentInfo {
@EmbeddedId
private StudentId studentId;
@Column(name = "name")
private String name;
}
// 復(fù)合主鍵類
@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;
}
實(shí)體間一對(duì)一的關(guān)系。
REMOVE:級(jí)聯(lián)刪除操作。刪除當(dāng)前實(shí)體時(shí),與它有映射關(guān)系的實(shí)體也會(huì)跟著被刪除。
MERGE:級(jí)聯(lián)更新(合并)操作。當(dāng)前對(duì)象中的數(shù)據(jù)改變,會(huì)相應(yīng)地更新級(jí)聯(lián)對(duì)象中的數(shù)據(jù)。
DETACH:級(jí)聯(lián)脫管/游離操作。如果要?jiǎng)h除一個(gè)實(shí)體,但是它有外鍵無法刪除,你就需要這個(gè)級(jí)聯(lián)權(quán)限了。它會(huì)撤銷所有相關(guān)的外鍵關(guān)聯(lián)。
REFRESH:級(jí)聯(lián)刷新操作。更新數(shù)據(jù)前先刷新對(duì)象和級(jí)聯(lián)對(duì)象,再更新。
PERSIST:級(jí)聯(lián)持久化(保存)操作。持久保存擁有方實(shí)體時(shí),也會(huì)持久保存該實(shí)體的所有相關(guān)數(shù)據(jù)。
ALL,當(dāng)前類增刪改查改變之后,關(guān)聯(lián)類跟著增刪改查,擁有以上所有級(jí)聯(lián)操作權(quán)
一對(duì)一關(guān)系的例子
people 表(id,name,sex,birthday,address_id) address 表(id,phone,zipcode,address)
People和Address是一對(duì)一的關(guān)系。
方式一:通過外鍵的方式(一個(gè)實(shí)體通過外鍵關(guān)聯(lián)到另一個(gè)實(shí)體的主鍵)
@JoinColum:保存表與表之間關(guān)系的字段,它要標(biāo)注在實(shí)體屬性上。一般修飾在主控方,用來定義一對(duì)一,一對(duì)多等關(guān)系列。
關(guān)聯(lián)的實(shí)體的主鍵一般是用來做外鍵的。但如果此時(shí)不想主鍵作為外鍵,則需要設(shè)置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是關(guān)系的維護(hù)端,當(dāng)刪除 people,會(huì)級(jí)聯(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;//手機(jī)
@Column(name = "zipcode")
private String zipcode;//郵政編碼
@Column(name = "address")
private String address;//地址
}
方式二:通過關(guān)聯(lián)表的方式來保存一對(duì)一的關(guān)系。
關(guān)聯(lián)表:people_address (people_id,address_id)
@JoinTable:用于構(gòu)建一對(duì)多,多對(duì)多時(shí)的連接表,默認(rèn)會(huì)以主控表加下劃線加反轉(zhuǎ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是關(guān)系的維護(hù)端
@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;//手機(jī)
@Column(name = "zipcode")
private String zipcode;//郵政編碼
@Column(name = "address")
private String address;//地址
}
注解一對(duì)多和多對(duì)一關(guān)系。
例子
@Entity
public class Author {
@Id
@Column(name = "id")
@GenericGenerator(name = "idGenerator", strategy = "uuid")
@GeneratedValue(generator = "idGenerator")
private String id;
@Column
private String name;//姓名
//級(jí)聯(lián)保存、更新、刪除、刷新;延遲加載。當(dāng)刪除用戶,會(huì)級(jí)聯(lián)刪除該用戶的所有文章
//擁有mappedBy注解的實(shí)體類為關(guān)系被維護(hù)端
//mappedBy="author"中的author是Article中的author屬性
@OneToMany(mappedBy = "author",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
private ListarticleList;//文章列表
}
@Entity
public class Article {
@Id
@Column(name = "id")
@GenericGenerator(name = "idGenerator", strategy = "uuid")
@GeneratedValue(generator = "idGenerator")
private String id;
@Column
private String title;
@Lob // 大對(duì)象,映射 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)
//設(shè)置在article表中的關(guān)聯(lián)字段(外鍵)
@JoinColumn(name="author_id")
private Author author;//所屬作者
}
注解多對(duì)多的關(guān)系。
角色和權(quán)限是多對(duì)多的關(guān)系。一個(gè)角色可以有多個(gè)權(quán)限,一個(gè)權(quán)限也可以被很多角色擁有。
JPA中使用@ManyToMany來注解多對(duì)多的關(guān)系,由一個(gè)關(guān)聯(lián)表來維護(hù)。這個(gè)關(guān)聯(lián)表的表名默認(rèn)是:主表名+下劃線+從表名。
這個(gè)關(guān)聯(lián)表只有兩個(gè)外鍵字段,分別指向主表ID和從表ID。字段的名稱默認(rèn)為:主表名+下劃線+主表中的主鍵列名,從表名+下劃線+從表中的主鍵列名。
例子
權(quán)限表 user_permission(id,permission_name)
角色表 user_role(id,department_id, create_time, description, name, update_time)
關(guān)聯(lián)表 user_role_permission 表(role_id, permission_id)
注意
多對(duì)多關(guān)系中一般不設(shè)置級(jí)聯(lián)保存、級(jí)聯(lián)刪除、級(jí)聯(lián)更新等操作。
本例中,由于加了@JoinTable注解,關(guān)聯(lián)關(guān)系表會(huì)按照注解指定的生成。否則去掉注解,指定Role為關(guān)系維護(hù)端,所以生成的關(guān)聯(lián)表名稱為:user_role_permission,關(guān)聯(lián)表的字段為:role_id 和permission_id。
@Data
@Entity
@Table(name = "user_permission")
public class Permission implements Comparable{
@Id
@Column(name = "id")
private String id;
@Column(name = "permission_name")
private String permissionName;
@ManyToMany(mappedBy="permissions")
private Setroles;
}
@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 Listpermissions;
}
以上就是 JPA 實(shí)體類中的注解介紹,文中的例子僅僅淺嘗輒止,希望大家可以實(shí)際應(yīng)用一下,后續(xù)我也會(huì)更深入的講解一些 JPA 的高級(jí)用法。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流