本週精心挑選9篇Java和Spring文章

banq發表於2024-05-26

精心挑選了一些值得一讀的有趣 Java 和 Spring 文章。這些文章包括並行流、JPA、快取、OpenAI API、Java 安全、Mockito 等主題。

1. 在 Spring Data JPA 中儲存後重新整理並獲取實體
本文討論瞭如何在 Spring Data JPA 中管理實體,特別關注儲存、獲取和重新整理實體。它涵蓋了如何設定 Spring Data JPA、定義實體以及使用方法save()來持久化資料。可以使用類似 的方法獲取實體findById(),並深入瞭解即時載入和延遲載入。

本文還介紹了refresh()更新陳舊實體的方法以及OptimisticLockException發生併發修改時的處理方法。這確保了應用程式中實體管理的穩健性和可靠性。

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ProductService {
    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public Product refreshProduct(Product product) {
        entityManager.refresh(product);
        return product;
    }
}


2.使用Spring實現兩級快取
在 Spring 中實現兩級快取可以顯著提高應用程式的效能和可擴充套件性。透過結合第一級記憶體快取和第二級分散式快取,開發人員可以確保更快的資料訪問並減少資料庫的負載。

這種方法尤其有利於讀取需求高且資料相對穩定的應用程式。第一級快取提供對常用資料的快速訪問,而第二級快取提供可擴充套件的解決方案,用於處理更大的資料集並確保多個例項之間的資料一致性。

  • caffeine:第一級快取
  • Redis:第二級快取

package com.jcg.example.config;

@Configuration
public class TwoLevelCacheConfig extends CachingConfigurerSupport {
   @Bean
   public RedisConnectionFactory redisConnectionFactory() {
       return new LettuceConnectionFactory();
   }

   @Bean
   public RedisTemplate redisTemplate() {
       RedisTemplate template = new RedisTemplate();
       template.setConnectionFactory(redisConnectionFactory());
       return template;
   }

   @Bean
   public CacheManager cacheManager() {
       CompositeCacheManager cacheManager = new CompositeCacheManager();
       CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager(<font>"items");
       caffeineCacheManager.setCaffeine(Caffeine.newBuilder()
               .initialCapacity(100)
               .maximumSize(500)
               .expireAfterAccess(10, TimeUnit.MINUTES));

       RedisCacheConfiguration redisCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
               .entryTtl(Duration.ofMinutes(10));
       RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory())
               .cacheDefaults(redisCacheConfig)
               .build();

       cacheManager.setCacheManagers(Arrays.asList(caffeineCacheManager, redisCacheManager));
       return cacheManager;
   }
}


3. Java 22 概覽:多檔案原始碼程式
Java 22 對多檔案原始碼程式的支援是 Java 朝著更易於訪問和更靈活的方向邁出的重要一步。它允許直接執行復雜的多檔案程式,而無需進行大量設定,從而簡化了初學者和經驗豐富的開發人員的開發工作流程。

這營造了一種有利於學習、快速原型設計和實驗的環境,使 Java 與其他現代程式語言的易用性更加接近。

<font>// MyAwesomeApp.java<i>
class MyAwesomeApp {

  public static void main(String... args) {
    new AwesomeFeature().doTheWork(args);
  }
}

// AwesomeFeature.java<i>
class AwesomeFeature {

  void doTheWork(String... args) {
   
// ...<i>
  }
}

4. Java 中的 OpenAI API 客戶端
它介紹了設定 Spring Boot 應用程式以呼叫 OpenAI ChatGPT API 的過程,該 API 根據給定的提示生成響應。關鍵步驟包括配置必要的依賴項、為請求和響應建立資料傳輸物件 (DTO) 以及使用 API 金鑰處理 API 身份驗證。

該指南強調使用 Spring Boot 的功能來有效管理 API 請求和響應,並提供了實際示例和程式碼片段以方便實施。

5. 使用 IdClass 將主鍵實現為Record記錄
本文探討了如何IdClass在 Java 中(特別是使用 Hibernate ORM 6.5.0 及更高版本)將主鍵實現為記錄。這種方法非常高效,提供不變性和內建的equals和hashCode方法。在 中建模的主鍵IdClass必須與實體的主鍵屬性相匹配。

由於內部例項化機制,Hibernate 要求記錄欄位按字母順序排列。本文還介紹瞭如何使用這些記錄及其侷限性,特別是在 Hibernate 6.5.0 之前的版本中。

有多種方式來實現您自己的主鍵:

  • 主鍵可由多個屬性組成。
  • 或者您遵循領域驅動的設計原則並希望使用自定義型別為其新增語義含義。

在這些情況下,實現記錄並將其對映為 IdClass 似乎是顯而易見的。記錄高效、易於實現、不可變(就像主鍵一樣),並提供 equals 和 hashCode 方法。

如果將其對映為 IdClass,則只需定義實體用作主鍵屬性的同一組欄位,並實現 equals和hashCode方法。其他一切都由 Hibernate 處理。

@Entity
@IdClass(ChessGameId.class)
public class ChessGame {

    @Id
    private int round;

    @Id
    private String playerWhite;
    
    @Id
    private String playerBlack;

    private ZonedDateTime dateTime;

    @Version
    private int version;

    ...
}

解釋:

  • ChessGame實體的主鍵由玩家的姓名和他們玩遊戲的回合組成。
  • @Id註釋註釋了這 3 個屬性, 以將它們標記為主鍵屬性。

Hibernate 和 Jakarta Persistence 規範要求每個實體物件的主鍵值都可以由單個主鍵物件表示。實現此目的的一種方法是提供 IdClass。

IdClass 必須由 @IdClass 註釋引用,並且必須為所有主鍵屬性建模,但不包括其他屬性。所有 IdClass 屬性的名稱和型別都必須與其對應的實體屬性相匹配。

因此,在這個例子中,ChessGameId必須對String型別的屬性playerWhite、String型別的屬性 playerBlack和int型別的屬性 round進行建模。

從 Hibernate ORM 6.5.0 開始,您可以將 IdClass 實現為記錄:

public record ChessGameId(String playerBlack, String playerWhite, int round) {}

在內部,Hibernate 使用EmbeddableInstantiator來例項化表示主鍵值的記錄。這對IdClass記錄的設計造成了重大限制。

  • 例項化新的 IdClass 記錄時,Hibernate 預設的EmbeddableInstantiator按照屬性名稱的字母順序提供主鍵屬性的值。
  • 在定義記錄時,您必須牢記這一點,並確保按字母順序定義其欄位。

使用 IdClass:

ChessGame game = new ChessGame();
game.setRound(1);
game.setPlayerWhite(<font>"Fabiano Caruana");
game.setPlayerBlack(
"Hikaru Nakamura");
game.setDateTime(ZonedDateTime.of(2024, 4, 4, 14, 30, 0, 0, ZoneId.of(
"America/Toronto")));
em.persist(game);

然後,Hibernate 將每個屬性對映到資料庫列:

16:02:34,659 DEBUG [org.hibernate.SQL] - 
    insert 
    into
        ChessGame
        (dateTime, version, playerBlack, playerWhite, round) 
    values
        (?, ?, ?, ?, ?)
16:02:34,662 TRACE [org.hibernate.orm.jdbc.bind] - binding parameter (1:TIMESTAMP_UTC) <- [2024-04-04T14:30-04:00[America/Toronto]]
16:02:34,662 TRACE [org.hibernate.orm.jdbc.bind] - binding parameter (2:INTEGER) <- [0]
16:02:34,662 TRACE [org.hibernate.orm.jdbc.bind] - binding parameter (3:VARCHAR) <- [Hikaru Nakamura]
16:02:34,663 TRACE [org.hibernate.orm.jdbc.bind] - binding parameter (4:VARCHAR) <- [Fabiano Caruana]
16:02:34,663 TRACE [org.hibernate.orm.jdbc.bind] - binding parameter (5:INTEGER) <- [1]

並且,當您呼叫EntityManager.find方法或使用 Hibernate 的任何其他基於主鍵的 API 時,您必須提供 IdClass 的物件。因此,在此示例中,我必須例項化ChessGameId記錄並將其作為引數提供給EntityManager.find方法。

em.find(ChessGame.class, new ChessGameId(<font>"Hikaru Nakamura", "Fabiano Caruana", 1));

然後,Hibernate 為主鍵的每個部分生成一個具有相等謂詞的查詢。


6. Java 安全性的簡單提示和應避免的錯誤
本文提供了增強 Java 應用程式安全性的實用技巧,並強調了應避免的常見錯誤。它涵蓋的主題包括使用安全編碼實踐、安全地管理依賴項、實施適當的身份驗證和授權機制、加密敏感資料、安全地處理異常以及及時更新安全補丁。

透過遵循這些提示並避免常見的陷阱,開發人員可以顯著改善其 Java 應用程式的安全態勢。

7.如何在Java中測試私有方法
本文介紹了測試私有 Java 方法的方法,這些方法很難從類外部直接訪問。建議透過更改訪問級別、使用反射間接訪問它們或在同一類中建立巢狀測試類或輔助方法,使它們可供測試訪問。

每種方法都有其優缺點,例如可讀性降低或潛在的效能開銷。關鍵是根據專案需求選擇最合適的方法,同時確保全面的測試覆蓋率而不損害程式碼完整性。

8. 使用 Mockito 在 Java 單元測試中模擬依賴關係的基礎知識
本文全面介紹瞭如何使用 Mockito 在 Java 單元測試中模擬依賴項。透過利用 Mockito 建立模擬物件和模擬依賴項的功能,開發人員可以編寫強大、獨立的單元測試,專注於各個元件的行為,最終提高程式碼質量和可維護性。


9.JobRunr 入門:強大的後臺作業處理庫
本文為有興趣利用 JobRunr 在其 Java 應用程式中進行任務排程和後臺處理的開發人員提供了全面的指南。透過提供詳細的說明、程式碼示例和整合技巧,它旨在促進順利的入職流程,並幫助開發人員充分利用 JobRunr 的潛力。

優點:

  • 開發人員友好: JobRunr 的 API 簡單、靈活、直接 - 設定簡單但廣泛。
  • 簡單採用: JobRunr 適用於任何軟體架構,並且只需要對程式碼庫進行很少的更改,同時只需要很少的依賴關係。
  • 框架整合: JobRunr 支援最流行的 Java 框架:Spring、Quarkus 和 Micronaut。
  • 各種儲存選項:持久儲存透過 RDBMS(例如 Postgres、MariaDB/MySQL、Oracle、SQL Server、DB2 和 SQLite)或 NoSQL(ElasticSearch、MongoDB 和 Redis)完成
  • 雲原生和雲無關:可在任何地方部署,無論是在您首選的雲提供商還是在本地
  • 分散式處理:規模不是問題——JobRunr 支援跨叢集的作業分配。
  • 容錯性:JobRunr 也具有容錯性 - 外部 Web 服務發生故障?不用擔心,該作業會使用智慧退避策略自動重試 10 次。重試策略當然是可配置的!
  • 實時監控: JobRunr 提供了一個儀表板,允許使用者監控作業、觸發或刪除重複作業以及重新排隊或刪除作業。
  • 虛擬執行緒: JobRunr 支援虛擬執行緒,以增加 I/O 作業的吞吐量。
  • 全面的文件:文件涵蓋了從設定到高階功能的所有內容,簡化了學習曲線。

程式碼: fork the example project

 

相關文章