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

Spring Data Jpa必殺技:12大實戰(zhàn)技巧讓開發(fā) & 性能飆升300%

開發(fā) 前端
隨著時間的推移,系統(tǒng)的數(shù)據(jù)量也隨之增大,我們都遇到過一些常見的挑戰(zhàn),比如查詢速度慢、管理復(fù)雜的關(guān)系、理解復(fù)雜的原生查詢或優(yōu)化接口效率。很多人都會遇到這些問題,解決這些問題對于提升我們的開發(fā)流程至關(guān)重要。

環(huán)境:SpringBoot3.4.2

1. 簡介

在基于Spring Boot 項目開發(fā)中,有一個關(guān)鍵組件是 Spring Data JPA,這是一個在數(shù)據(jù)處理方面表現(xiàn)出色的 API。它在我們的開發(fā)過程中具有不可忽視的重要性。

它不僅僅是一個工具,而是一個強大的工具,能夠顯著提升我們的開發(fā)流程,讓我們有信心和能力高效地處理復(fù)雜的數(shù)據(jù)管理任務(wù)。

最常用的默認(rèn)注解包括:

  • @Repository:用于標(biāo)記或注解一個扮演數(shù)據(jù)訪問對象(DAO)角色的類,通常我們是不需要寫該注解的。
  • @Query:允許開發(fā)者使用原生查詢的注解。

隨著時間的推移,系統(tǒng)的數(shù)據(jù)量也隨之增大,我們都遇到過一些常見的挑戰(zhàn),比如查詢速度慢、管理復(fù)雜的關(guān)系、理解復(fù)雜的原生查詢或優(yōu)化接口效率。很多人都會遇到這些問題,解決這些問題對于提升我們的開發(fā)流程至關(guān)重要。

接下來,我們將由淺入深的詳細(xì)介紹Spring Data JPA實戰(zhàn)技巧開發(fā)。

2.實戰(zhàn)案例

2.1 基本概念

開發(fā)中,在定義接口時,我們通??梢岳^承:Repository,CrudRepository,PagingAndSortingRepository以及JpaRepository接口。

Repository

Repository 是最基本的接口,通常不包含任何方法。它不提供任何功能,但作為 Spring Data JPA 中所有其他倉庫接口的基礎(chǔ)接口。

public interface UserRepository extends Repository<User, Long> {
  // 沒有預(yù)定義的方法
}

不建議使用該接口,因為它沒有提供任務(wù)功能,僅起到了標(biāo)記作用。

CrudRepository

CrudRepository 接口提供了 CRUD 操作。如果你需要基本的數(shù)據(jù)訪問能力而不需要排序或分頁,該接口非常適合你。

public interface UserRepository extends CrudRepository<User, Long> {
  // 提供了基本的 CRUD 方法
}

常用的基本方法:

  • save(S entity):保存給定的實體
  • findById(ID id):通過 ID 檢索實體
  • existsById(ID id):返回是否存在具有給定 ID 的實體
  • findAll():返回所有實體
  • deleteById(ID id):刪除具有給定 ID 的實體

PagingAndSortingRepository

該接口添加了分頁和排序的方法。這在處理大型數(shù)據(jù)集并在頁面上顯示數(shù)據(jù)時非常有用。這個接口也包含了 CRUD 操作。

public interface UserRepository extends PagingAndSortingRepository<User, Long> {
  // CRUD 方法加上分頁和排序
}

這個接口的額外方法包括:

  • findAll(Pageable pageable):返回符合 Pageable 對象中提供的分頁限制的實體頁面。
  • findAll(Sort sort):返回按給定選項排序的所有實體。

JpaRepository

這個接口添加了 JPA 特定的方法,并提供了一套完整的 JPA 相關(guān)方法,如批量操作、自定義查詢和刷新控制。這使得它成為 JPA 應(yīng)用程序中最強大和最靈活的選項。

public interface UserRepository extends JpaRepository<User, Long> {
  // 完整的 CRUD 方法、分頁、排序和 JPA 特定方法
}

這個接口提供了一套全面的 JPA 相關(guān)操作方法,允許你執(zhí)行各種任務(wù)而無需額外的接口或自定義代碼。

使用 JpaRepository,你可以通過遵循 findBy 后跟屬性名的命名約定來定義自定義查詢方法。Spring Data JPA 將根據(jù)方法名自動生成查詢。

public interface UserRepository extends JpaRepository<User, Long> {
  // 通過 ID 查找實體
  Optional<User> findById(Long id) ;
  // 查找所有具有給定名稱的實體
  List<User> findByName(String name) ;
  // 查找年齡大于給定值的實體
  List<User> findByAgeGreaterThan(int age) ;
}

為什么選擇 JpaRepository?

  • 功能全面:它結(jié)合了 CRUD、分頁、排序和 JPA 特定操作在一個接口中。
  • 便捷性:通過提供所有必要的方法簡化了代碼。
  • 性能:通過批量操作和刷新控制優(yōu)化了性能。
  • 靈活性:允許自定義查詢方法并支持 JPQL(Java 持久化查詢語言)和原生 SQL 查詢。

2.2 使用 Specification 和 Criteria Builder

在使用 Spring Data JPA 時,有時我們需要更復(fù)雜的查詢,這些查詢無法通過簡單的查詢方法輕松實現(xiàn)。這時,Specification 和 Criteria Builder 就派上了用場,它們允許你構(gòu)建動態(tài)查詢并處理復(fù)雜的場景。

Specification

Specification 是 Spring Data JPA 中的一個函數(shù)式接口,用于基于 JPA 條件創(chuàng)建動態(tài)查詢。它提供了一種以編程方式構(gòu)建查詢的方法。當(dāng)查詢條件在編譯時未知時,它非常有用。

import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;


public class UserSpecification {
  public static Specification<MyEntity> hasName(String name) {
    return (Root<MyEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
      return cb.equal(root.get("name"), name);
    };
  }
}

使用

private final UserRepository userRepository ;


Specification<User> spec = UserSpecification.hasName("Pack");
List<User> results = userRepository.findAll(spec) ;

Criteria Builder

Criteria Builder API 是 JPA 的一部分,允許創(chuàng)建類型安全的查詢。它提供了一種使用 Java 對象而不是硬編碼字符串來動態(tài)構(gòu)建查詢的方式。如下示例:

@Service
public class UserService {
  
  @PersistenceContext
  private EntityManager em;


  public List<User> findByName(String name) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<User> query = cb.createQuery(User.class);
    Root<User> root = query.from(User.class);
    // 構(gòu)建查詢
    query.select(root).where(cb.equal(root.get("name"), name));
    return em.createQuery(query).getResultList();
  }
}

你可以結(jié)合多個條件來構(gòu)建更復(fù)雜的查詢。例如,你可以使用 and 和 or 來組合條件。

public class UserSpecification {
  public static Specification<User> hasName(String name) {
    return (Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
      return cb.equal(root.get("name"), name);
    };
  }
  public static Specification<User> hasStatus(Integer status) {
    return (Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
      return cb.equal(root.get("status"), status);
    };
  }
  public static Specification<User> hasAgeGreaterThan(int age) {
    return (Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
      return cb.greaterThan(root.get("age"), age);
    };
  }
  public static Specification<User> hasNameAndStatus(String name, Integer status) {
    return (Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
      Predicate namePredicate = cb.equal(root.get("name"), name);
      Predicate statusPredicate = cb.equal(root.get("status"), status);
      return cb.and(namePredicate, statusPredicate);
    };
  }
}
// 使用
Specification<User> spec = UserSpecification.hasNameAndStatus("Pack", 1) ;
List<User> results = userRepository.findAll(spec) ;

結(jié)合多個規(guī)范可以創(chuàng)建更靈活和可重用的查詢條件。

Specification<User> spec = Specification.where(UserSpecification.hasName("Pack"))
    .and(UserSpecification.hasStatus(1))
    .and(UserSpecification.hasAgeGreaterThan(25));
List<User> results = myEntityRepository.findAll(spec);

2.3 開發(fā)技巧

為了最大化 Spring Data JPA 的效用,遵循一些提示和技巧是至關(guān)重要的。這些可以幫助你優(yōu)化應(yīng)用程序、避免常見陷阱,并確保你的代碼是可維護和高效的。

使用懶加載

默認(rèn)情況下,將實體關(guān)系設(shè)置為 FetchType.LAZY,這意味著相關(guān)實體在訪問之前不會從數(shù)據(jù)庫加載。雖然這可以節(jié)省資源,但如果處理不當(dāng),也可能導(dǎo)致 N+1 選擇問題。

最佳實踐:對于大型或很少訪問的關(guān)系,使用懶加載。對于頻繁訪問的關(guān)系,考慮使用迫切加載。

@Entity
public class Customer {
  @OneToMany(fetch = FetchType.LAZY, mappedBy = "customer")
  private List<Order> orders ;
}

優(yōu)化查詢

能用一個構(gòu)建良好的查詢完成任務(wù)時,就不要運行多個查詢。必要時,使用 JPQL、Criteria API 或原生查詢來優(yōu)化性能。

最佳實踐:使用自定義查詢或規(guī)范將相關(guān)查詢合并為單個數(shù)據(jù)庫訪問操作。

@Query("SELECT e FROM User e JOIN FETCH e.orders WHERE e.name = :name")
List<MyEntity> findByNameWithOrders(@Param("name") String name);

利用緩存

緩存可以顯著提高應(yīng)用程序的性能,通過減少數(shù)據(jù)庫命中次數(shù)。Spring 提供了與 Ehcache、Redis 等緩存解決方案的輕松集成。

最佳實踐:緩存不經(jīng)常更改的頻繁訪問數(shù)據(jù)。

private final UserRepository userRepository ;


@Cacheable("users")
public List<User> findAll() {
  return userRepository.findAll();
}

批量處理

在保存或刪除多個實體時,批量處理可以減少數(shù)據(jù)庫往返次數(shù)并提高性能。

最佳實踐:使用 saveAll 進行批量插入,使用 deleteInBatch 進行批量刪除。

private final UserRepository userRepository ;


public void saveUsers(List<User> users) {
  userRepository.saveAll(users);
}
public void deleteUsers(List<User> users) {
  userRepository.deleteInBatch(users);
}

適當(dāng)?shù)氖褂檬聞?wù)

確保你的數(shù)據(jù)庫操作被正確地包裹在事務(wù)中,以維護數(shù)據(jù)完整性。使用 Spring 的 @Transactional 注解來管理事務(wù)。

最佳實踐:在服務(wù)層使用 @Transactional,以確保方法內(nèi)的所有操作都是單個事務(wù)的一部分。

@Service
public class UserService {
  private final UserRepository userRepository ;
  @Transactional
  public void updateUsers(List<User> users) {
    for (User user: users) {
      userRepository.save(user) ;
    }
  }
}

save方法的內(nèi)部是使用了 @Transactional 注解。

避免N+1問題

N+1 選擇問題發(fā)生在應(yīng)用程序為了獲取 N 個實體的集合(每個實體都有自己的相關(guān)實體)而發(fā)出 N+1 個數(shù)據(jù)庫查詢時,這會嚴(yán)重影響性能。

最佳實踐:在你的 JPQL 查詢中使用 JOIN FETCH 來在單個查詢中獲取相關(guān)實體。

@Query("SELECT e FROM Customer e JOIN FETCH e.orders WHERE e.status = :status")
List<Customer> findByStatusWithOrders(@Param("status") Integer status);

日志記錄&監(jiān)控

在開發(fā)過程中啟用 SQL 日志記錄,以了解 Hibernate 生成的查詢。這可以幫助識別和優(yōu)化低效的查詢。

最佳實踐:使用日志記錄來監(jiān)控 SQL 查詢和性能指標(biāo)。

spring:
  jpa:
    show-sql=true
  properties
    hibernate:
      '[format_sql]': true
      # 慢SQL閾值
      '[log_slow_query]': 1000

使用投影

有時,你只需要幾個字段而不是整個實體。使用投影來僅選擇必要的數(shù)據(jù)。

最佳實踐:使用投影來僅獲取所需的字段,減少從數(shù)據(jù)庫傳輸?shù)臄?shù)據(jù)量。

public interface UserProjection {
  String getName();
  String getStatus();
}


@Query("SELECT e.name AS name, e.status AS status FROM User e WHERE e.age > :age")
List<UserProjection> queryUser(@Param("age") int age) ;

使用視圖

有時,你的選擇查詢會變得更加復(fù)雜。創(chuàng)建虛擬表或表視圖可以幫助簡化數(shù)據(jù)訪問。

最佳實踐:使用視圖可以簡化 SELECT 語句,減少復(fù)雜性并避免潛在錯誤。

審計功能

Spring Data 支持實體變更審計(創(chuàng)建者/修改者/時間),我們能通過注解非常方便的應(yīng)用審計功能。通過 @CreatedBy 和 @LastModifiedBy 來獲取創(chuàng)建或修改實體的用戶,以及 @CreatedDate 和 @LastModifiedDate 來獲取更改發(fā)生的時間。

@Entity
@EntityListeners(AuditingEntityListener.class)
public class User {
  @CreatedDate
  private LocalDateTime createTime;
  @LastModifiedDate
  private LocalDateTime updateTime;
  @CreatedBy
  private String createdBy;
  @LastModifiedBy
  private String updatedBy;
}

接下來,還需要提供如下組件用來獲取用戶。

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

鎖機制

要指定查詢方法使用的鎖模式,可以在查詢方法上使用 @Lock 注解,具體示例如下:

public interface ProductRepository extends JpaRepository<Product, Long> {


  @Transactional
  @Lock(LockModeType.PESSIMISTIC_READ)
  public Product findByName(String name) ;
}

注意:這里我們需要 @Transactional 事務(wù)注解。

運行輸出SQL如下:

SELECT
  p1_0.id,
  p1_0.NAME,
  p1_0.price,
  p1_0.quantity 
FROM
  t_product p1_0 
WHERE
  p1_0.NAME =? FOR SHARE

自動添加了 FOR SHARE。

流式查詢

可以使用 Java 8 的 Stream<T> 作為返回類型來增量處理查詢方法的結(jié)果。并非將查詢結(jié)果包裝在 Stream 中,而是使用特定于數(shù)據(jù)存儲的方法來執(zhí)行流處理,如以下示例所示:

@Query("select u from User u")
Stream<User> findUserByStream();

流可能會封裝底層特定于數(shù)據(jù)存儲的資源,因此在使用后必須關(guān)閉。您可以使用 close() 方法手動關(guān)閉流,或者使用 Java 7 中的 try-with-resources 塊,如下例所示:

try (Stream<User> stream = repository.findUserByStream()) {
  stream.forEach(…) ;
}


責(zé)任編輯:武曉燕 來源: Springboot實戰(zhàn)案例錦集
相關(guān)推薦

2024-08-09 12:11:07

2010-08-11 16:43:05

職場

2018-09-21 14:32:00

iPaas云應(yīng)用部署

2010-08-24 14:57:33

外企職場

2011-06-27 14:56:49

SEO

2009-09-28 11:16:23

UPS電源

2013-12-18 11:34:17

云文件共享服務(wù)云文件同步服務(wù)BYOD

2025-04-07 02:33:00

項目開發(fā)Spring

2013-05-10 09:23:14

iPaaS混合云集成云集成

2021-02-02 10:55:09

等級保護2.0信息安全網(wǎng)絡(luò)安全

2009-07-22 15:02:18

2012-05-29 10:19:41

2012-05-22 09:06:25

2009-10-13 16:38:04

強行關(guān)閉VMware虛

2014-08-05 15:36:04

騰訊云CDN

2023-04-07 17:44:43

2011-06-24 17:23:30

網(wǎng)站優(yōu)化

2009-01-03 09:14:00

2009-06-08 09:08:21

職場裁員必殺技

2012-03-06 11:25:40

ibmdw
點贊
收藏

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