首頁 > 軟體

Spring Data JPA註解Entity使用範例詳解

2022-09-30 14:00:39

1、JPA協定中關於Entity的相關規定

(1)實體是直接進行資料庫持久化操作的領域物件(即一個簡單的POJO),必須通過@Entity註解進行標示。

(2)實體必須有一個 public 或者 projected的無引數構造方法.

(3)持久化對映的註解可以標示在Entity的欄位field上(比較適合使用Lombok的情況),如下所示

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(columnDefinition = "int(11) NOT NULL COMMENT '主鍵' ")
private Integer id;
@Column(columnDefinition = "varchar(30) DEFAULT '' COMMENT '書名'")
private String bookName;
@Column(columnDefinition = "int(11) DEFAULT 0  COMMENT '數量'")
private Integer amount;

除此之外,也可以將持久化註解運用在Entity裡面的get/set方法上,通過我們放在get方法中,如下所示:
需要注意的是: 在實體類get方法中加註解時,必須保證set方法的存在,否則會報錯

@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;
}

需要注意的是:

在同一個Entity裡面只能有一種方式生效,也就是說註解要麼全部寫在field上面,要麼就全部寫在get/set方法上

  • 只要是在@Entity的實體裡面被註解標註的欄位,都會被對映到資料庫中,除了使用@Transient註解的欄位之外。
  • 實體裡面必須有一個主鍵。主鍵表示的欄位可以是單個欄位,也可以是複合主鍵欄位。

2、常用註解

2.1 JPA支援的註解

2.2 常用註解

@Entity必填項。用於定義物件將會成為被JPA管理的實體,將欄位對映到指定的資料庫表中,使用起來很簡單,直接用在實體類上面即可。

 @Target(TYPE) // 表示此註解只能用在class上面
 @Retention(RUNTIME)
 public @interface Entity {
    // 預設是實體類的名字
    String name() default "";
 }

@Table非必填項。 用於指定資料庫的表名,表示此實體對應的資料庫裡面的表名。 預設表名和entity名字一樣

  @Target(TYPE)  // 表示此註解只能用在class上面
  @Retention(RUNTIME)
  public @interface Table {
      // 表的名字,預設表名和entity名字一樣
      String name() default "";
      // 表的目錄
      String catalog() default "";
      // 此表所在schema
      String schema() default "";
      // 唯一性約束,在建立表的時候有用,表建立好之後後面就不需要了
      UniqueConstraint[] uniqueConstraints() default {};
      // 索引,在建立表的時候使用,表建立之後後面就不需要了
      Index[] indexes() default {};
  }
  // 單一欄位唯一性約束
  uniqueConstraints = {@UniqueConstraint(name = "unique_age",columnNames = "age")}
  // 聯合約束
  uniqueConstraints = {@UniqueConstraint(name = "unique_name",columnNames = {"name","age"})}
  // 索引
  indexes = {@Index(name = "nameIndex",columnList = "name")})

@Access非必填項。 用於指定entity裡面的註解是寫在欄位上面,還是get/set方法上面生效。如果預設不填寫的情況下,當實體裡面的第一個註解出現在欄位上或者 get/set方法上面,就以第一次出現的方式為準。

@Target( { TYPE, METHOD, FIELD }) // 表示此註解可以運用在類上(可以指定實體的預設註解生成策略),也可以用在方法上或欄位上(表示可以獨立設定某一個欄位或者方法的生效策略)
@Retention(RUNTIME)
public @interface Access {
    AccessType value();
}
public enum AccessType {
    FIELD,
    PROPERTY
}
@Access(value = AccessType.FIELD)

@Id定義屬性為資料庫的主鍵,一個實體裡面必須有一個主鍵,但不一定是這個註解。可以和@GeneratedValue配合使用或成對出現。

@GeneratedValue主鍵生成策略,如下所示:

public @interface GeneratedValue {
    // Id的生成策略
    GenerationType strategy() default AUTO;
    // 通過Sequences生成Id,常見的是Oracle資料庫ID生成規則,這個時候需要配合@SequenceGenerator使用
    String generator() default "";
}
// 生成策略
public enum GenerationType { 
    // 通過表產生主鍵,框架藉由表模擬序列產生主鍵,使用該策略可以使應用更易於資料庫移植
    TABLE, 
    // 通過序列產生主鍵,通過@SequenceGenerator 註解指定序列名,MySql不支援這種方式
    SEQUENCE, 
    // 採用資料庫Id自增長,一般用於Mysql資料庫
    IDENTITY, 
    // 自動選擇合適的策略,是預設選項;
    AUTO
}

@Enumerated對Enum列舉類對映到資料庫提供下標和name兩種方式,用法就是直接對映在enum列舉型別的欄位上。

@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface Enumerated {
    EnumType value() default ORDINAL;
}
public enum EnumType {
    // 對映列舉欄位的下標
    ORDINAL,
    // 對映列舉的Name
    STRING
}

@Basic表示屬性是到資料表欄位的對映。如果實體的欄位上沒有任何註解,預設即為@Basic。也就是說預設所有的欄位肯定是和資料庫進行對映的,並且預設為Eager型別。

public @interface Basic {
    // EAGER 立即記載;LAZY 延遲載入;
    FetchType fetch() default EAGER;
    // 這個欄位是否可以為null,預設是true
    boolean optional() default true;
}

@Transient表示非持久化屬性。 JPA對映資料庫的時候忽略它,與@Basic有相反的作用。

@Column 定義該屬性對應資料庫中的

public @interface Column {
    // 定義了被標註欄位在資料庫表中所對應欄位的名稱;
    String name() default "";
    // 表示該欄位是否為唯一標識
    boolean unique() default false;
    // 資料欄位是否允許為空,預設為空
    boolean nullable() default true;
    // 表示在使用「INSERT」指令碼插入資料時,是否需要插入該欄位的值。
    boolean insertable() default true;
    // 表示在使用「UPDATE」指令碼插入資料時,是否需要更新該欄位的值
    boolean updatable() default true;
    // 表示建立表時,該欄位建立的SQL語句,一般用於通過Entity生成表定義時使用
    String columnDefinition() default "";
    // 表示當對映多個表時,指定表的表中的欄位。預設值為主表的表名。
    String table() default "";
    // 表示欄位的長度,當欄位的型別為varchar時,該屬性才有效,預設為255個字元。
    int length() default 255;
    // 表示數值的總長度
    int precision() default 0;
    // 表示小數點所佔的位數,必須和precision搭配使用
    int scale() default 0;
}

3、聯合主鍵

3.1 @IdClass

第一步:新建一個UserInfo類裡面的屬性是聯合主鍵

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserInfoID implements Serializable {
    private String name;
    private String telephone;
}

第二步 :再新建一個UserInfo的實體,採用@IdClass參照聯合主鍵類

@Entity
@Data
@Builder
@IdClass(UserInfoID.class)
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo {
    private Integer ages;
    @Id
    private String name;
    @Id
    private String telephone;
}

第三步:新增一個UserInfoRepo類來做持久化操作

public interface UserInfoRepo extends JpaRepository<UserInfo, UserInfoID> {
}

第四步:測試用例

@Test
public void queryIndex2(){
    userInfoRepo.save(UserInfo.builder()
    .ages(1)
    .name("jack")
    .telephone("123456789").build());
    userInfoRepo.findById(UserInfoID.builder()
            .name("jack")
            .telephone("123456789").build());
}

通過上面例子我們可以發現,我們的表的主鍵是primary key(name,telephone),而Entity裡面不再是一個@Id欄位。

執行的SQL如下:

3.2 @Embeddable與@EmbeddedId註解使用

第一步:在上面例子中的UserInfoID裡面新增@Embeddable註解

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class UserInfoID implements Serializable {
    private String name;
    private String telephone;
}

第二步:在UserInfo類中,刪除@IdClass,新增@EmbeddeId註解,如下:

@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo {
    private Integer ages;
    @EmbeddedId
    private UserInfoID userInfoID;
    @Column(unique = true)
    private String uniqueNumber;
}

第三步:UserInfoRepo保持不變 第四步:測試用例

@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());
}

執行的SQL如下所示:

3.3 兩者的區別是什麼?

  • @Embedded用的是物件,@IdClass用的具體的某一個欄位

以上就是Spring Data JPA註解Entity使用範例詳解的詳細內容,更多關於Spring Data JPA註解Entity的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com