偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

強(qiáng)大!Spring Boot + JPA 實(shí)體類(lèi)設(shè)計(jì)五大實(shí)戰(zhàn)技巧

開(kāi)發(fā) 項(xiàng)目管理
本篇文章我們將深入探討基于Spring Boot項(xiàng)目開(kāi)發(fā)時(shí),如何利用JPA設(shè)計(jì)實(shí)體類(lèi)的重要最佳實(shí)踐。通過(guò)遵循這些最佳實(shí)踐,開(kāi)發(fā)人員可以確保應(yīng)用程序的完整性、性能和可擴(kuò)展性。

環(huán)境:SpringBoot3.4.2

1. 簡(jiǎn)介

項(xiàng)目開(kāi)發(fā)中,實(shí)體類(lèi)的有效設(shè)計(jì)和實(shí)現(xiàn)對(duì)于構(gòu)建健壯且易于維護(hù)的應(yīng)用程序至關(guān)重要。JPA與Spring Boot的強(qiáng)大功能相結(jié)合,使開(kāi)發(fā)人員能夠簡(jiǎn)化數(shù)據(jù)庫(kù)操作并創(chuàng)建高度功能化的應(yīng)用程序。

本篇文章我們將深入探討基于Spring Boot項(xiàng)目開(kāi)發(fā)時(shí),如何利用JPA設(shè)計(jì)實(shí)體類(lèi)的重要最佳實(shí)踐。通過(guò)遵循這些最佳實(shí)踐,開(kāi)發(fā)人員可以確保應(yīng)用程序的完整性、性能和可擴(kuò)展性。

2. 最佳實(shí)踐

2.1 實(shí)體類(lèi)與繼承

  • 使用@Entity注解來(lái)標(biāo)記您的實(shí)體類(lèi),以表明它們是JPA實(shí)體
  • 如果表名與類(lèi)名不同,請(qǐng)使用@Table注解來(lái)指定表名
  • 對(duì)于應(yīng)由多個(gè)實(shí)體繼承的公共屬性,可以考慮使用@MappedSuperclass

實(shí)體類(lèi)基類(lèi)設(shè)計(jì)

@MappedSuperclass
public abstract class BaseEntity implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  // 其它公共屬性
  @Temporal(TemporalType.TIMESTAMP)
  private Date createTime ;
  //getters, setters
}

BaseEntity類(lèi)被注解為@MappedSuperclass。它包含了你希望在多個(gè)實(shí)體類(lèi)之間共享的公共字段。Employee類(lèi)繼承自BaseEntity,也就從超類(lèi)繼承了id, createTime字段。通過(guò)基類(lèi)的設(shè)計(jì)實(shí)現(xiàn)了代碼的復(fù)用性,并保持了實(shí)體層次的清晰和結(jié)構(gòu)化。

具體實(shí)體類(lèi)

@Entity
@Table(name = "t_employees")
public class Employee extends BaseEntity {
  
  private String name ;
  private String address ;
  // getters, setters
}

主鍵說(shuō)明

  • 主鍵字段使用@Id注解
  • 主鍵生成策略使用@GeneratedValue注解(該注解有多種生成策略,如:GenerationType.IDENTITY、GenerationType.SEQUENCE等)

關(guān)聯(lián)關(guān)系

  • 使用@OneToOne、@OneToMany、@ManyToOne和@ManyToMany來(lái)定義實(shí)體之間的關(guān)系
  • 使用fetch屬性來(lái)控制加載行為(例如,LAZY(延遲加載)或EAGER(急切加載))
  • 利用mappedBy來(lái)定義雙向關(guān)聯(lián)中的擁有方
@Entity
@Table(name = "t_department")
public class Department extends BaseEntity {
  private String name;
  private String code ;
  @OneToMany(mappedBy = "department")
  private List<Employee> employees = new ArrayList<>() ;
  // getters, setters
}
@Entity
@Table(name = "t_employee")
public class Employee extends BaseEntity {
  // ...
  @ManyToOne
  @JoinColumn(name = "department_id")
  private Department department;
  // getters, setters
}

級(jí)聯(lián)操作

  • 使用cascade屬性來(lái)指定級(jí)聯(lián)操作(例如,CascadeType.ALL、CascadeType.PERSIST)
  • 在使用級(jí)聯(lián)刪除(CascadeType.DELETE)時(shí)要特別小心,以避免意外丟失數(shù)據(jù)
     
public class Department extends BaseEntity {
  // ...
  @OneToMany(mappedBy = "department", 
    cascade = {
      CascadeType.REFRESH, 
      CascadeType.PERSIST, 
      CascadeType.REMOVE
    },
    orphanRemoval = true
  )
  private List<Employee> employees = new ArrayList<>() ;
}

說(shuō)明:

  • 如果你將級(jí)聯(lián)操作設(shè)置為CascadeType.ALL,所有操作(例如,持久化、合并、刪除)都應(yīng)該從父實(shí)體(Department)級(jí)聯(lián)到子實(shí)體(Employee)
  • orphanRemoval = true:此選項(xiàng)指定當(dāng)從Department集合中移除對(duì)某個(gè)Employee實(shí)體的引用時(shí),這個(gè)孤立的Employee實(shí)體也應(yīng)該從數(shù)據(jù)庫(kù)中刪除

如下示例,保存Department時(shí)會(huì)級(jí)聯(lián)保存所有的Employee。

@Resource
private DepartmentRepository departmentRepository ;
@Test
public void testSave() {
  Department department = new Department() ;
  department.setCode("S0001") ;
  department.setName("研發(fā)部") ;
  Employee e1 = new Employee("張三", "SC") ;
  e1.setDepartment(department) ;
  Employee e2 = new Employee("Pack", "XJ") ;
  e2.setDepartment(department) ;
  department.setEmployees(List.of(e1, e2)) ;
    
  this.departmentRepository.saveAndFlush(department) ;
}

控制臺(tái)輸出

同樣也適用于其它的級(jí)聯(lián)操作。

2.2 有效性驗(yàn)證

  • 使用驗(yàn)證注解(如@NotNull、@Size等)直接在實(shí)體類(lèi)中強(qiáng)制實(shí)施數(shù)據(jù)完整性約束。
  • 將JPA驗(yàn)證與Spring的@Valid注解結(jié)合使用,以自動(dòng)驗(yàn)證傳入的數(shù)據(jù)。
@Entity
@Table(name = "t_department")
public class Department extends BaseEntity {
  @NotEmpty(message = "部門(mén)名稱(chēng)不能為空")
  @Length(min = 2)
  private String name;
  @NotEmpty(message = "部門(mén)代碼不能為空")
  private String code ;
}

當(dāng)我們執(zhí)行如下代碼時(shí)程序?qū)伋霎惓?/p>

@Test
public void testSave() {
  Department department = new Department() ;
  department.setCode("S0001") ;
  // 沒(méi)有設(shè)置name屬性
  this.departmentRepository.saveAndFlush(department) ;
}

注意,你需要開(kāi)啟如下配置:

spring:
  jpa:
    properties:
      hibernate:
        '[javax.persistence.validation.mode]': auto

2.3 審計(jì)

  • 通過(guò)添加如@CreatedBy、@CreatedDate、@LastModifiedBy和@LastModifiedDate等字段來(lái)實(shí)現(xiàn)實(shí)體審計(jì),以跟蹤是哪個(gè)用戶(hù)何時(shí)創(chuàng)建或修改了實(shí)體
  • 利用Spring的@EntityListeners來(lái)管理審計(jì)行為

如下比較完善的一個(gè)實(shí)體基類(lèi)

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class AuditableEntity implements Serializable {
  private static final long serialVersionUID = 1L;
  
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id ;
  @Temporal(TemporalType.TIMESTAMP)
  private Date createTime = new Date() ;
  @CreatedBy
  protected String createdBy;
  @CreatedDate
  @Column(nullable = false, updatable = false)
  protected LocalDateTime createdDate;
  @LastModifiedBy
  protected String lastModifiedBy;
  @LastModifiedDate
  protected LocalDateTime lastModifiedDate;
}

如上我們又定義了一個(gè)可以審計(jì)的實(shí)體基類(lèi);如果哪個(gè)實(shí)體需要被審計(jì)那么就繼承該類(lèi)即可。

@Entity
@Table(name = "t_product")
public class Product extends AuditableEntity {


  private String name;
  private Double price;
  // getters, setters
}

注意,要使得審計(jì)功能生效,我們還需要做如下配置:

開(kāi)啟審計(jì)功能。

@Configuration
@EnableJpaAuditing
public class JpaConfig {
}

當(dāng)前審計(jì)人Bean。

我們需要提供一個(gè)你當(dāng)前操作的人是誰(shuí)的bean。

@Component
public class SystemAuditorAware implements AuditorAware<String> {
  @Override
  public Optional<String> getCurrentAuditor() {
    return Optional.of("Pack") ;
  }
}

這里你需要根據(jù)自己的實(shí)際情況來(lái)編寫(xiě)。

2.4 DTO映射

  • 當(dāng)查詢(xún)數(shù)據(jù)時(shí),考慮使用DTO投影來(lái)僅查詢(xún)需要的字段,從而提高性能
  • 使用Spring Data JPA的@Query注解或查詢(xún)方法來(lái)創(chuàng)建自定義投影

如下實(shí)體類(lèi)

@Entity
@Table(name = "t_author")
public class Author extends BaseEntity {
  private String name ;
  private Integer age ;
  private String address ;
  private String sex ;
  private String email ;
}

該實(shí)體字段表多,我們可能只需要部分字段,如:name,sex,那么我們可以定義如下的投影:

public interface AuthorProjection {
  
  String getName();
  String getSex();
}

使用@Query查詢(xún)

public interface AuthorRepository extends JpaRepository<Author, Long> {


  @Query("select e.name as name, e.sex as sex from Author e")
  List<AuthorProjection> queryAuthors() ;
}

注意,你需要在sql中使用 as 別名。

2.5 索引

在實(shí)體類(lèi)上我們可以通過(guò)@Table注解的indexes屬性指定列來(lái)創(chuàng)建索引。

@Entity
@Table(name = "t_author", indexes = {
    @Index(columnList = "name, sex")
})
public class Author extends BaseEntity {}

當(dāng)服務(wù)啟動(dòng)時(shí),會(huì)自動(dòng)創(chuàng)建基于 "name", "sex" 2個(gè)字段的聯(lián)合索引。

索引對(duì)于提高查詢(xún)性能至關(guān)重要,尤其是在處理大型數(shù)據(jù)集時(shí)。根據(jù)你應(yīng)用程序的查詢(xún)模式,仔細(xì)選擇哪些列要?jiǎng)?chuàng)建索引是非常關(guān)鍵的。

責(zé)任編輯:武曉燕 來(lái)源: Springboot實(shí)戰(zhàn)案例源碼
相關(guān)推薦

2024-11-19 15:22:37

2025-02-13 08:06:54

2025-06-11 04:44:00

技巧Spring性能

2025-03-20 08:49:01

2010-08-05 14:16:37

路由器配置

2025-05-14 01:00:00

Spring工具工廠類(lèi)

2019-04-12 10:03:38

云端數(shù)據(jù)集成數(shù)字化

2023-01-04 08:53:52

JPA實(shí)體類(lèi)注解

2021-11-22 11:42:19

IT風(fēng)險(xiǎn)風(fēng)險(xiǎn)評(píng)估框架網(wǎng)絡(luò)安全

2025-02-21 16:00:00

SpringBoot代碼開(kāi)發(fā)

2013-09-02 10:15:42

云備份云存儲(chǔ)云安全

2012-05-29 09:59:34

2014-02-18 09:37:54

政府云計(jì)算

2021-06-11 10:02:39

語(yǔ)言編程開(kāi)發(fā)

2013-11-08 14:20:31

設(shè)計(jì)頁(yè)面設(shè)計(jì)

2019-06-04 10:40:07

2010-07-14 17:03:52

編程語(yǔ)言

2013-11-26 09:10:26

優(yōu)化網(wǎng)絡(luò)基礎(chǔ)設(shè)施技巧

2017-01-12 11:07:25

網(wǎng)絡(luò)數(shù)據(jù)技巧

2024-12-31 08:03:12

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)