Spring?Data?JPA注解Entity使用示例詳解
1、JPA協(xié)議中關(guān)于Entity的相關(guān)規(guī)定
(1)實(shí)體是直接進(jìn)行數(shù)據(jù)庫(kù)持久化操作的領(lǐng)域?qū)ο螅匆粋€(gè)簡(jiǎn)單的POJO),必須通過(guò)@Entity注解進(jìn)行標(biāo)示。
(2)實(shí)體必須有一個(gè) public 或者 projected的無(wú)參數(shù)構(gòu)造方法.
(3)持久化映射的注解可以標(biāo)示在Entity的字段field上(比較適合使用Lombok的情況),如下所示
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(columnDefinition = "int(11) NOT NULL COMMENT '主鍵' ") private Integer id; @Column(columnDefinition = "varchar(30) DEFAULT '' COMMENT '書(shū)名'") private String bookName; @Column(columnDefinition = "int(11) DEFAULT 0 COMMENT '數(shù)量'") private Integer amount;
除此之外,也可以將持久化注解運(yùn)用在Entity里面的get/set方法上,通過(guò)我們放在get方法中,如下所示:
需要注意的是: 在實(shí)體類(lèi)get方法中加注解時(shí),必須保證set方法的存在,否則會(huì)報(bào)錯(cuò)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(columnDefinition = "int(11) NOT NULL COMMENT '主鍵' ")
public Integer getId() {
return id;
}
@Column(columnDefinition = "varchar(30) DEFAULT '' COMMENT '寵物名'")
public String getName() {
return name;
}
@Column(columnDefinition = "int(11) DEFAULT NULL COMMENT '年齡'")
public Integer getAge() {
return age;
}
需要注意的是:
在同一個(gè)Entity里面只能有一種方式生效,也就是說(shuō)注解要么全部寫(xiě)在field上面,要么就全部寫(xiě)在get/set方法上
- 只要是在@Entity的實(shí)體里面被注解標(biāo)注的字段,都會(huì)被映射到數(shù)據(jù)庫(kù)中,除了使用@Transient注解的字段之外。
- 實(shí)體里面必須有一個(gè)主鍵。主鍵表示的字段可以是單個(gè)字段,也可以是復(fù)合主鍵字段。
2、常用注解
2.1 JPA支持的注解

2.2 常用注解
@Entity必填項(xiàng)。用于定義對(duì)象將會(huì)成為被JPA管理的實(shí)體,將字段映射到指定的數(shù)據(jù)庫(kù)表中,使用起來(lái)很簡(jiǎn)單,直接用在實(shí)體類(lèi)上面即可。
@Target(TYPE) // 表示此注解只能用在class上面
@Retention(RUNTIME)
public @interface Entity {
// 默認(rèn)是實(shí)體類(lèi)的名字
String name() default "";
}
@Table非必填項(xiàng)。 用于指定數(shù)據(jù)庫(kù)的表名,表示此實(shí)體對(duì)應(yīng)的數(shù)據(jù)庫(kù)里面的表名。 默認(rèn)表名和entity名字一樣
@Target(TYPE) // 表示此注解只能用在class上面
@Retention(RUNTIME)
public @interface Table {
// 表的名字,默認(rèn)表名和entity名字一樣
String name() default "";
// 表的目錄
String catalog() default "";
// 此表所在schema
String schema() default "";
// 唯一性約束,在創(chuàng)建表的時(shí)候有用,表創(chuàng)建好之后后面就不需要了
UniqueConstraint[] uniqueConstraints() default {};
// 索引,在創(chuàng)建表的時(shí)候使用,表創(chuàng)建之后后面就不需要了
Index[] indexes() default {};
}
// 單一字段唯一性約束
uniqueConstraints = {@UniqueConstraint(name = "unique_age",columnNames = "age")}
// 聯(lián)合約束
uniqueConstraints = {@UniqueConstraint(name = "unique_name",columnNames = {"name","age"})}
// 索引
indexes = {@Index(name = "nameIndex",columnList = "name")})
@Access非必填項(xiàng)。 用于指定entity里面的注解是寫(xiě)在字段上面,還是get/set方法上面生效。如果默認(rèn)不填寫(xiě)的情況下,當(dāng)實(shí)體里面的第一個(gè)注解出現(xiàn)在字段上或者 get/set方法上面,就以第一次出現(xiàn)的方式為準(zhǔn)。
@Target( { TYPE, METHOD, FIELD }) // 表示此注解可以運(yùn)用在類(lèi)上(可以指定實(shí)體的默認(rèn)注解生成策略),也可以用在方法上或字段上(表示可以獨(dú)立設(shè)置某一個(gè)字段或者方法的生效策略)
@Retention(RUNTIME)
public @interface Access {
AccessType value();
}
public enum AccessType {
FIELD,
PROPERTY
}
@Access(value = AccessType.FIELD)
@Id定義屬性為數(shù)據(jù)庫(kù)的主鍵,一個(gè)實(shí)體里面必須有一個(gè)主鍵,但不一定是這個(gè)注解??梢院虭GeneratedValue配合使用或成對(duì)出現(xiàn)。
@GeneratedValue主鍵生成策略,如下所示:
public @interface GeneratedValue {
// Id的生成策略
GenerationType strategy() default AUTO;
// 通過(guò)Sequences生成Id,常見(jiàn)的是Oracle數(shù)據(jù)庫(kù)ID生成規(guī)則,這個(gè)時(shí)候需要配合@SequenceGenerator使用
String generator() default "";
}
// 生成策略
public enum GenerationType {
// 通過(guò)表產(chǎn)生主鍵,框架借由表模擬序列產(chǎn)生主鍵,使用該策略可以使應(yīng)用更易于數(shù)據(jù)庫(kù)移植
TABLE,
// 通過(guò)序列產(chǎn)生主鍵,通過(guò)@SequenceGenerator 注解指定序列名,MySql不支持這種方式
SEQUENCE,
// 采用數(shù)據(jù)庫(kù)Id自增長(zhǎng),一般用于Mysql數(shù)據(jù)庫(kù)
IDENTITY,
// 自動(dòng)選擇合適的策略,是默認(rèn)選項(xiàng);
AUTO
}
@Enumerated對(duì)Enum枚舉類(lèi)映射到數(shù)據(jù)庫(kù)提供下標(biāo)和name兩種方式,用法就是直接映射在enum枚舉類(lèi)型的字段上。
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Enumerated {
EnumType value() default ORDINAL;
}
public enum EnumType {
// 映射枚舉字段的下標(biāo)
ORDINAL,
// 映射枚舉的Name
STRING
}
@Basic表示屬性是到數(shù)據(jù)表字段的映射。如果實(shí)體的字段上沒(méi)有任何注解,默認(rèn)即為@Basic。也就是說(shuō)默認(rèn)所有的字段肯定是和數(shù)據(jù)庫(kù)進(jìn)行映射的,并且默認(rèn)為Eager類(lèi)型。
public @interface Basic {
// EAGER 立即記載;LAZY 延遲加載;
FetchType fetch() default EAGER;
// 這個(gè)字段是否可以為null,默認(rèn)是true
boolean optional() default true;
}
@Transient表示非持久化屬性。 JPA映射數(shù)據(jù)庫(kù)的時(shí)候忽略它,與@Basic有相反的作用。
@Column 定義該屬性對(duì)應(yīng)數(shù)據(jù)庫(kù)中的
public @interface Column {
// 定義了被標(biāo)注字段在數(shù)據(jù)庫(kù)表中所對(duì)應(yīng)字段的名稱(chēng);
String name() default "";
// 表示該字段是否為唯一標(biāo)識(shí)
boolean unique() default false;
// 數(shù)據(jù)字段是否允許為空,默認(rèn)為空
boolean nullable() default true;
// 表示在使用“INSERT”腳本插入數(shù)據(jù)時(shí),是否需要插入該字段的值。
boolean insertable() default true;
// 表示在使用“UPDATE”腳本插入數(shù)據(jù)時(shí),是否需要更新該字段的值
boolean updatable() default true;
// 表示創(chuàng)建表時(shí),該字段創(chuàng)建的SQL語(yǔ)句,一般用于通過(guò)Entity生成表定義時(shí)使用
String columnDefinition() default "";
// 表示當(dāng)映射多個(gè)表時(shí),指定表的表中的字段。默認(rèn)值為主表的表名。
String table() default "";
// 表示字段的長(zhǎng)度,當(dāng)字段的類(lèi)型為varchar時(shí),該屬性才有效,默認(rèn)為255個(gè)字符。
int length() default 255;
// 表示數(shù)值的總長(zhǎng)度
int precision() default 0;
// 表示小數(shù)點(diǎn)所占的位數(shù),必須和precision搭配使用
int scale() default 0;
}
3、聯(lián)合主鍵
3.1 @IdClass
第一步:新建一個(gè)UserInfo類(lèi)里面的屬性是聯(lián)合主鍵
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserInfoID implements Serializable {
private String name;
private String telephone;
}
第二步 :再新建一個(gè)UserInfo的實(shí)體,采用@IdClass引用聯(lián)合主鍵類(lèi)
@Entity
@Data
@Builder
@IdClass(UserInfoID.class)
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo {
private Integer ages;
@Id
private String name;
@Id
private String telephone;
}
第三步:新增一個(gè)UserInfoRepo類(lèi)來(lái)做持久化操作
public interface UserInfoRepo extends JpaRepository<UserInfo, UserInfoID> {
}
第四步:測(cè)試用例
@Test
public void queryIndex2(){
userInfoRepo.save(UserInfo.builder()
.ages(1)
.name("jack")
.telephone("123456789").build());
userInfoRepo.findById(UserInfoID.builder()
.name("jack")
.telephone("123456789").build());
}
通過(guò)上面例子我們可以發(fā)現(xiàn),我們的表的主鍵是primary key(name,telephone),而Entity里面不再是一個(gè)@Id字段。

執(zhí)行的SQL如下:

3.2 @Embeddable與@EmbeddedId注解使用
第一步:在上面例子中的UserInfoID里面添加@Embeddable注解
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class UserInfoID implements Serializable {
private String name;
private String telephone;
}
第二步:在UserInfo類(lèi)中,刪除@IdClass,添加@EmbeddeId注解,如下:
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo {
private Integer ages;
@EmbeddedId
private UserInfoID userInfoID;
@Column(unique = true)
private String uniqueNumber;
}
第三步:UserInfoRepo保持不變 第四步:測(cè)試用例
@Test
public void queryIndex(){
userInfoRepo.save(UserInfo.builder()
.ages(1)
.userInfoID(UserInfoID.builder()
.name("jack")
.telephone("123456789").build()).build());
userInfoRepo.findById(UserInfoID.builder()
.name("jack")
.telephone("123456789").build());
}
執(zhí)行的SQL如下所示:

3.3 兩者的區(qū)別是什么?
- @Embedded用的是對(duì)象,@IdClass用的具體的某一個(gè)字段
以上就是Spring Data JPA注解Entity使用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring Data JPA注解Entity的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java 的雙重分發(fā)與 Visitor 模式實(shí)例詳解
這篇文章主要介紹了Java 的雙重分發(fā)與 Visitor 模式實(shí)例詳解,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-07-07
Java中的while無(wú)限循環(huán)結(jié)構(gòu)及實(shí)例
這篇文章主要介紹了Java中的while無(wú)限循環(huán)結(jié)構(gòu)及實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
如何利用Java實(shí)現(xiàn)MySQL的數(shù)據(jù)變化監(jiān)聽(tīng)
在高并發(fā)和大數(shù)據(jù)環(huán)境下,實(shí)時(shí)獲取?MySQL?數(shù)據(jù)庫(kù)的增量變化對(duì)數(shù)據(jù)同步、數(shù)據(jù)分析、緩存更新等場(chǎng)景至關(guān)重要,下面我們就來(lái)看看如何通過(guò)Java實(shí)現(xiàn)MySQL的數(shù)據(jù)變化監(jiān)聽(tīng)吧2025-02-02
SparkSQL使用IDEA快速入門(mén)DataFrame與DataSet的完美教程
本文給大家介紹使用idea開(kāi)發(fā)Spark SQL 的詳細(xì)過(guò)程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-08-08
Java多種方法實(shí)現(xiàn)合并多個(gè)list對(duì)象列表
Java編程中,合并多個(gè)列表對(duì)象可以通過(guò)Stream?API或傳統(tǒng)循環(huán)方式實(shí)現(xiàn),使用Stream?API合并時(shí),利用flatMap方法將嵌套的List展平,再通過(guò)collect方法收集成一個(gè)新的列表,傳統(tǒng)循環(huán)則通過(guò)創(chuàng)建一個(gè)空的ArrayList,并通過(guò)遍歷每個(gè)列表將元素添加進(jìn)去2024-09-09
springboot依賴(lài)沖突問(wèn)題及解決過(guò)程
新搭了一個(gè)springboot 2.3.7.RELASE的框架,在集成mysql,tkMapper,mybatis的過(guò)程中,啟動(dòng)報(bào)錯(cuò),怎么解決這個(gè)問(wèn)題呢,下面小編給大家?guī)?lái)了springboot依賴(lài)沖突問(wèn)題及解決過(guò)程,一起看看吧2021-09-09
Spring中的Aware接口及應(yīng)用場(chǎng)景詳解
這篇文章主要介紹了Spring中的Aware接口及應(yīng)用場(chǎng)景,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Java并發(fā)容器相關(guān)知識(shí)總結(jié)
今天給大家?guī)?lái)的文章是Java并發(fā)容器的相關(guān)知識(shí),文中有非常詳細(xì)的介紹,對(duì)正在學(xué)習(xí)Java并發(fā)容器的小伙伴們很有幫助,需要的朋友可以參考下2021-06-06

