package com.example.accessingdatajpa;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
protected Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format(
"Customer[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
使用 JPA 存取資料
本指南將逐步引導您建構一個應用程式,該應用程式使用 Spring Data JPA 在關聯式資料庫中儲存和檢索資料。
您將建構什麼
您將建構一個應用程式,該應用程式在記憶體資料庫中儲存 Customer
POJO(Plain Old Java Objects,簡單的 Java 物件)。
您需要什麼
-
約 15 分鐘
-
您慣用的文字編輯器或 IDE
-
Java 17 或更高版本
-
您也可以直接將程式碼匯入到您的 IDE 中
如何完成本指南
與大多數 Spring 入門指南一樣,您可以從頭開始並完成每個步驟,或者您可以略過您已熟悉的基礎設定步驟。無論哪種方式,您最終都會得到可運作的程式碼。
若要從頭開始,請繼續前往 從 Spring Initializr 開始。
若要略過基礎知識,請執行以下操作
-
下載 並解壓縮本指南的原始碼儲存庫,或使用 Git 複製它:
git clone https://github.com/spring-guides/gs-accessing-data-jpa.git
-
cd 到
gs-accessing-data-jpa/initial
-
跳到 定義簡單實體。
當您完成時,您可以對照 gs-accessing-data-jpa/complete
中的程式碼檢查您的結果。
從 Spring Initializr 開始
您可以使用這個 預先初始化的專案,然後點擊 Generate (產生) 以下載 ZIP 檔案。此專案已設定為符合本教學中的範例。
若要手動初始化專案
-
導覽至 https://start.spring.io。此服務會拉取應用程式所需的所有相依性,並為您完成大部分設定。
-
選擇 Gradle 或 Maven 以及您要使用的語言。本指南假設您選擇 Java。
-
點擊 Dependencies (相依性) 並選取 Spring Data JPA,然後選取 H2 Database (H2 資料庫)。
-
點擊 Generate (產生)。
-
下載產生的 ZIP 檔案,這是一個已使用您的選擇設定的 Web 應用程式的封存檔。
如果您的 IDE 具有 Spring Initializr 整合,您可以從您的 IDE 完成此程序。 |
您也可以從 Github 分支專案,並在您的 IDE 或其他編輯器中開啟它。 |
定義簡單實體
在本範例中,您儲存 Customer
物件,每個物件都標註為 JPA 實體。以下清單顯示 Customer 類別 (位於 src/main/java/com/example/accessingdatajpa/Customer.java
中)
這裡您有一個 Customer
類別,其中包含三個屬性:id
、firstName
和 lastName
。您也有兩個建構子。預設建構子僅為了 JPA 的緣故而存在。您不會直接使用它,因此它被指定為 protected
。另一個建構子是您用來建立 Customer
實例以儲存到資料庫的建構子。
Customer
類別使用 @Entity
進行標註,表示它是一個 JPA 實體。(由於沒有 @Table
註解存在,因此假定此實體對應到名為 Customer
的資料表。)
Customer
物件的 id
屬性使用 @Id
進行標註,以便 JPA 將其識別為物件的 ID。id
屬性也使用 @GeneratedValue
進行標註,以表示 ID 應自動產生。
其他兩個屬性 firstName
和 lastName
則未標註。假定它們對應到與屬性本身同名的資料行。
方便的 toString()
方法會印出客戶的屬性。
建立簡單查詢
Spring Data JPA 專注於使用 JPA 在關聯式資料庫中儲存資料。其最引人注目的功能是能夠在執行時期,從儲存庫介面自動建立儲存庫實作。
若要了解其運作方式,請建立一個與 Customer
實體搭配使用的儲存庫介面,如下列清單所示 (位於 src/main/java/com/example/accessingdatajpa/CustomerRepository.java
中)
package com.example.accessingdatajpa;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
Customer findById(long id);
}
CustomerRepository
擴展了 CrudRepository
介面。它使用的實體和 ID 類型 Customer
和 Long
在 CrudRepository
的泛型參數中指定。透過擴展 CrudRepository
,CustomerRepository
繼承了多種方法來處理 Customer
持續性,包括用於儲存、刪除和尋找 Customer
實體的方法。
Spring Data JPA 也允許您透過宣告其方法簽名來定義其他查詢方法。例如,CustomerRepository
包含 findByLastName()
方法。
在典型的 Java 應用程式中,您可能會期望編寫一個實作 CustomerRepository
的類別。然而,這正是 Spring Data JPA 如此強大的原因:您不需要編寫儲存庫介面的實作。當您執行應用程式時,Spring Data JPA 會建立一個實作。
現在您可以連接這個範例並看看它的樣子!
建立應用程式類別
Spring Initializr 為應用程式建立了一個簡單的類別。以下清單顯示 Initializr 為本範例建立的類別 (位於 src/main/java/com/example/accessingdatajpa/AccessingDataJpaApplication.java
中)
package com.example.accessingdatajpa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AccessingDataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(AccessingDataJpaApplication.class, args);
}
}
@SpringBootApplication
是一個方便的註解,它新增了以下所有內容
-
@Configuration
:將此類別標記為應用程式內容的 Bean 定義來源。 -
@EnableAutoConfiguration
:告訴 Spring Boot 根據類別路徑設定、其他 Bean 和各種屬性設定開始新增 Bean。例如,如果spring-webmvc
在類別路徑上,則此註解會將應用程式標記為 Web 應用程式,並啟動關鍵行為,例如設定DispatcherServlet
。 -
@ComponentScan
:告訴 Spring 在com/example
套件中尋找其他元件、組態和服務,使其能夠找到控制器。
main()
方法使用 Spring Boot 的 SpringApplication.run()
方法來啟動應用程式。您是否注意到沒有單行 XML?也沒有 web.xml
檔案。這個 Web 應用程式是 100% 純 Java,您不必處理任何管道或基礎架構的設定。
現在您需要修改 Initializr 為您建立的簡單類別。為了取得輸出 (在本範例中為控制台),您需要設定記錄器。然後您需要設定一些資料並使用它來產生輸出。以下清單顯示完成的 AccessingDataJpaApplication
類別 (位於 src/main/java/com/example/accessingdatajpa/AccessingDataJpaApplication.java
中)
package com.example.accessingdatajpa;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class AccessingDataJpaApplication {
private static final Logger log = LoggerFactory.getLogger(AccessingDataJpaApplication.class);
public static void main(String[] args) {
SpringApplication.run(AccessingDataJpaApplication.class);
}
@Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a few customers
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
repository.save(new Customer("Kim", "Bauer"));
repository.save(new Customer("David", "Palmer"));
repository.save(new Customer("Michelle", "Dessler"));
// fetch all customers
log.info("Customers found with findAll():");
log.info("-------------------------------");
repository.findAll().forEach(customer -> {
log.info(customer.toString());
});
log.info("");
// fetch an individual customer by ID
Customer customer = repository.findById(1L);
log.info("Customer found with findById(1L):");
log.info("--------------------------------");
log.info(customer.toString());
log.info("");
// fetch customers by last name
log.info("Customer found with findByLastName('Bauer'):");
log.info("--------------------------------------------");
repository.findByLastName("Bauer").forEach(bauer -> {
log.info(bauer.toString());
});
log.info("");
};
}
}
AccessingDataJpaApplication
類別包含一個 demo()
方法,該方法對 CustomerRepository
進行了一些測試。首先,它從 Spring 應用程式內容中提取 CustomerRepository
。然後它儲存一些 Customer
物件,示範 save()
方法並設定一些要處理的資料。接下來,它呼叫 findAll()
以從資料庫中提取所有 Customer
物件。然後它呼叫 findById()
以依其 ID 提取單個 Customer
。最後,它呼叫 findByLastName()
以尋找所有姓氏為 "Bauer" 的客戶。demo()
方法傳回一個 CommandLineRunner
Bean,該 Bean 會在應用程式啟動時自動執行程式碼。
預設情況下,Spring Boot 會啟用 JPA 儲存庫支援,並在 @SpringBootApplication 所在的套件 (及其子套件) 中尋找。如果您的組態具有位於不可見套件中的 JPA 儲存庫介面定義,您可以使用 @EnableJpaRepositories 及其型別安全 basePackageClasses=MyRepository.class 參數來指出替代套件。 |
建構可執行 JAR
您可以使用 Gradle 或 Maven 從命令列執行應用程式。您也可以建構一個包含所有必要相依性、類別和資源的單個可執行 JAR 檔案並執行它。建構可執行 JAR 可以輕鬆地在整個開發生命週期、跨不同環境等情況下,將服務作為應用程式交付、版本控制和部署。
如果您使用 Gradle,您可以使用 ./gradlew bootRun
來執行應用程式。或者,您可以使用 ./gradlew build
來建構 JAR 檔案,然後執行 JAR 檔案,如下所示
如果您使用 Maven,您可以使用 ./mvnw spring-boot:run
來執行應用程式。或者,您可以使用 ./mvnw clean package
來建構 JAR 檔案,然後執行 JAR 檔案,如下所示
此處描述的步驟會建立可執行的 JAR。您也可以建構經典 WAR 檔案。 |
當您執行應用程式時,您應該會看到類似以下的輸出
== Customers found with findAll(): Customer[id=1, firstName='Jack', lastName='Bauer'] Customer[id=2, firstName='Chloe', lastName='O'Brian'] Customer[id=3, firstName='Kim', lastName='Bauer'] Customer[id=4, firstName='David', lastName='Palmer'] Customer[id=5, firstName='Michelle', lastName='Dessler'] == Customer found with findById(1L): Customer[id=1, firstName='Jack', lastName='Bauer'] == Customer found with findByLastName('Bauer'): Customer[id=1, firstName='Jack', lastName='Bauer'] Customer[id=3, firstName='Kim', lastName='Bauer']
總結
恭喜!您已經編寫了一個簡單的應用程式,該應用程式使用 Spring Data JPA 將物件儲存到資料庫並從資料庫中提取物件,所有這些都無需編寫具體的儲存庫實作。
如果您想輕鬆地使用基於超媒體的 RESTful 前端公開 JPA 儲存庫,您可能想閱讀 使用 REST 存取 JPA 資料。 |