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(普通 Java 物件)儲存在記憶體資料庫中的應用程式。
您需要什麼
-
大約 15 分鐘
-
您喜歡的文字編輯器或 IDE
-
Java 17 或更高版本
-
您也可以直接將程式碼匯入到您的 IDE 中
如何完成本指南
像大多數 Spring 入門指南一樣,您可以從頭開始並完成每個步驟,或者跳過您已經熟悉的基本設定步驟。無論哪種方式,您最終都會得到可執行的程式碼。
要從頭開始,請繼續閱讀使用 Spring Initializr 入門。
要跳過基礎知識,請執行以下操作:
-
下載並解壓本指南的原始碼倉庫,或使用Git克隆:
git clone https://github.com/spring-guides/gs-accessing-data-jpa.git
-
進入
gs-accessing-data-jpa/initial
目錄 -
跳到定義一個簡單的實體。
完成後,您可以對照 gs-accessing-data-jpa/complete
目錄中的程式碼檢查您的結果。
使用 Spring Initializr 入門
您可以使用此預初始化專案,然後單擊“生成”下載 ZIP 檔案。此專案已配置為符合本教程中的示例。
手動初始化專案
-
導航到https://start.spring.io。此服務會拉取您應用程式所需的所有依賴項,併為您完成大部分設定工作。
-
選擇 Gradle 或 Maven 以及您想使用的語言。本指南假設您選擇 Java。
-
單擊依賴項,選擇Spring Data JPA,然後選擇H2 Database。
-
單擊生成。
-
下載生成的 ZIP 檔案,這是一個根據您的選擇配置好的 Web 應用程式歸檔。
如果您的 IDE 集成了 Spring Initializr,您也可以直接在 IDE 中完成此過程。 |
您也可以從 Github fork 專案,並在您的 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 為您建立的簡單類。為了獲得輸出(在此示例中是控制檯輸出),您需要設定一個 logger。然後您需要設定一些資料並使用它來生成輸出。以下列表顯示了完成的 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 資料。 |