Spring Boot JPA 是用于管理的Java規(guī)范Java應(yīng)用程序中的關(guān)系數(shù)據(jù)。它允許我們?cè)L問(wèn)和持久化Java對(duì)象/類(lèi)與關(guān)系數(shù)據(jù)庫(kù)之間的數(shù)據(jù)。 JPA遵循對(duì)象關(guān)系映射(ORM)。它是一組接口。它還提供了運(yùn)行時(shí) EntityManager API,用于處理針對(duì)數(shù)據(jù)庫(kù)對(duì)象的查詢(xún)和事務(wù)。它使用與平臺(tái)無(wú)關(guān)的面向?qū)ο蟮牟樵?xún)語(yǔ)言JPQL(Java持久查詢(xún)語(yǔ)言)。
在持久性方面,它涵蓋了三個(gè)領(lǐng)域:
Java持久性API Object-Relational元數(shù)據(jù)在 persistence 包中定義的API本身
JPA不是框架。它定義了可以在任何框架中實(shí)現(xiàn)的概念。
與JDBC相比,JPA更簡(jiǎn)單,更清潔且勞動(dòng)強(qiáng)度更低,SQL和手寫(xiě)映射。 JPA適用于非性能導(dǎo)向的復(fù)雜應(yīng)用程序。與JDBC相比,JPA的主要優(yōu)點(diǎn)在于,在JPA中,數(shù)據(jù)由對(duì)象和類(lèi)表示,而在JDBC中,數(shù)據(jù)由表和記錄表示。它使用POJO表示持久數(shù)據(jù),從而簡(jiǎn)化了數(shù)據(jù)庫(kù)編程。 JPA還有其他優(yōu)點(diǎn):
JPA避免使用SQL的特定于數(shù)據(jù)庫(kù)的方言編寫(xiě)DDL。取而代之的是,它允許以XML或使用Java注解進(jìn)行映射。 JPA允許我們避免用SQL的數(shù)據(jù)庫(kù)專(zhuān)用方言編寫(xiě)DML。 JPA允許我們完全不使用任何DML語(yǔ)言來(lái)保存和加載Java對(duì)象和圖形。當(dāng)我們需要執(zhí)行查詢(xún)JPQL時(shí),它允許我們用Java實(shí)體而不是(本機(jī))SQL表和列來(lái)表達(dá)查詢(xún)。
JPA具有以下功能:
這是一個(gè)功能強(qiáng)大的存儲(chǔ)庫(kù)和自定義的對(duì)象映射抽象。 它支持跨商店持久性。這意味著一個(gè)實(shí)體可以部分存儲(chǔ)在MySQL和Neo4j(圖形數(shù)據(jù)庫(kù)管理系統(tǒng))中。它從查詢(xún)方法名稱(chēng)動(dòng)態(tài)生成查詢(xún)。域基類(lèi)提供基本屬性。它支持透明審核。集成自定義存儲(chǔ)庫(kù)代碼的可能性。通過(guò)自定義名稱(chēng)空間很容易與Spring Framework集成。
JPA是將業(yè)務(wù)實(shí)體存儲(chǔ)為關(guān)系實(shí)體的源。它顯示了如何將POJO定義為實(shí)體以及如何通過(guò)關(guān)系管理實(shí)體。
下圖描述了JPA的類(lèi)級(jí)別體系結(jié)構(gòu),該體系結(jié)構(gòu)描述了JPA的核心類(lèi)和接口。 javax持久性包。 JPA體系結(jié)構(gòu)包含以下單元:
Persistence: 這是一個(gè)包含用于獲取EntityManagerFactory實(shí)例的靜態(tài)方法的類(lèi)。 EntityManagerFactory: 是EntityManager的工廠類(lèi)。它創(chuàng)建和管理EntityManager的多個(gè)實(shí)例。 EntityManager: 。它是一個(gè)界面。它控制對(duì)對(duì)象的持久性操作。它適用于Query實(shí)例。 Entity: 實(shí)體是作為記錄存儲(chǔ)在數(shù)據(jù)庫(kù)中的持久性對(duì)象。 Persistence Unit: 它定義了一組所有實(shí)體類(lèi)。在應(yīng)用程序中,EntityManager實(shí)例對(duì)其進(jìn)行管理。一組實(shí)體類(lèi)表示包含在單個(gè)數(shù)據(jù)存儲(chǔ)中的數(shù)據(jù)。 EntityTransaction: 它與EntityManager類(lèi)具有一對(duì)一關(guān)系。對(duì)于每個(gè)EntityManager,操作都由EntityTransaction類(lèi)維護(hù)。 Query: 該接口由每個(gè)JPA供應(yīng)商實(shí)現(xiàn),以獲取符合條件的關(guān)系對(duì)象。
我們上面討論的類(lèi)和接口保持一種關(guān)系。下圖顯示了類(lèi)和接口之間的關(guān)系。
EntityManager和EntiyTransaction之間的關(guān)系是一對(duì)一。每個(gè)EntityManager操作都有一個(gè)EntityTransaction實(shí)例。 EntityManageFactory和EntiyManager之間的關(guān)系是一對(duì)多。這是EntityManager實(shí)例的工廠類(lèi)。 EntityManager和Query之間的關(guān)系是一對(duì)多。我們可以使用EntityManager類(lèi)的實(shí)例執(zhí)行任意數(shù)量的查詢(xún)。 EntityManager和Entity之間的關(guān)系是一對(duì)多。 EntityManager實(shí)例可以管理多個(gè)實(shí)體。
JPA是一種開(kāi)源API。有各種企業(yè)供應(yīng)商,例如Eclipse,RedHat,Oracle等,通過(guò)在其中添加JPA來(lái)提供新產(chǎn)品。有一些流行的JPA實(shí)現(xiàn)框架,例如 Hibernate,EclipseLink,DataNucleus 等。它也稱(chēng)為對(duì)象關(guān)系映射(ORM)工具。
在ORM中,Java對(duì)象到數(shù)據(jù)庫(kù)表的映射(反之亦然)被稱(chēng)為對(duì)象關(guān)系映射。 ORM映射充當(dāng)關(guān)系數(shù)據(jù)庫(kù)(表和記錄)和 Java應(yīng)用程序(類(lèi)和對(duì)象)之間的橋梁。
在下面如圖所示,ORM層是適配器層。它將對(duì)象圖的語(yǔ)言適應(yīng)SQL和關(guān)系表的語(yǔ)言。
ORM層存在于應(yīng)用程序和數(shù)據(jù)庫(kù)之間。它轉(zhuǎn)換Java類(lèi)和對(duì)象,以便可以在關(guān)系數(shù)據(jù)庫(kù)中存儲(chǔ)和管理它們。默認(rèn)情況下,持久化的名稱(chēng)將成為表的名稱(chēng),而字段將成為列。一旦應(yīng)用程序建立,每個(gè)表行都對(duì)應(yīng)一個(gè)對(duì)象。
EJB的早期版本定義了與業(yè)務(wù)邏輯層結(jié)合的持久層。使用 javax.ejb.EntityBean 接口。 EJB規(guī)范包括JPA的定義。
在引入EJB 3.0時(shí),持久層被分離并指定為JPA 1.0(Java Persistence API)。該API的規(guī)范已與2006年5月11日使用JSR 220的JAVA EE5規(guī)范一起發(fā)布。
2019年,JPA重命名為 Jakarta Persistence 。 JPA的最新版本是 2.2 。它支持以下功能:
Java 8,數(shù)據(jù)和時(shí)間API AttributeConvertes中的CDI注入它使注解@Repeatable
JPA: JPA是一種Java規(guī)范,用于訪問(wèn),管理和持久化之間的數(shù)據(jù)Java對(duì)象和關(guān)系數(shù)據(jù)庫(kù)。這是ORM的標(biāo)準(zhǔn)方法。
Hibernate: 這是一種輕量級(jí)的開(kāi)源ORM工具,用于在關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)中存儲(chǔ)Java對(duì)象。它是JPA的提供者。它遵循JPA提供的一種通用方法。
下表描述了JPA和Hibernate之間的區(qū)別。
JPA | Hibernate |
JPA是用于在Java應(yīng)用程序中映射關(guān)系數(shù)據(jù)的 Java規(guī)范。 | Hibernate是一個(gè)用于處理數(shù)據(jù)持久性的 ORM框架。 |
JPA不提供任何實(shí)現(xiàn)類(lèi)。 | 它提供了實(shí)現(xiàn)類(lèi)。 |
它使用稱(chēng)為 JPQL (Java持久性查詢(xún)語(yǔ)言)的平臺(tái)無(wú)關(guān)的查詢(xún)語(yǔ)言。 | 它使用自己的稱(chēng)為 HQL 的查詢(xún)語(yǔ)言(Hibernate查詢(xún)語(yǔ)言)。 |
它在 javax.persistence 包中定義。 | 它在 org.hibernate 包中定義。 |
它在 Hibernate,EclipseLink 等各種ORM工具中實(shí)現(xiàn)。 | Hibernate是JPA的提供者。 |
JPA使用 EntityManager 處理數(shù)據(jù)的持久性。 | 在Hibernate中,使用 Session 處理數(shù)據(jù)的持久性。 |
Spring Boot提供了啟動(dòng)程序依賴(lài)項(xiàng) spring-boot-starter-data-jpa 以連接Spring Boot應(yīng)用程序高效地使用關(guān)系數(shù)據(jù)庫(kù)。 spring-boot-starter-data-jpa在內(nèi)部使用spring-boot-jpa依賴(lài)項(xiàng)。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.2.2.RELEASE</version> </dependency>
我們創(chuàng)建一個(gè)使用JPA連接到數(shù)據(jù)庫(kù)的Spring Boot應(yīng)用程序。在下面的示例中,我們使用了內(nèi)存數(shù)據(jù)庫(kù) Apache Derby。
Apache Derby : 這是一個(gè)嵌入式的開(kāi)源軟件關(guān)系數(shù)據(jù)庫(kù)完全用Java實(shí)現(xiàn)。它在Apache License 2.0下可用。 Apache Derby具有以下優(yōu)點(diǎn):
易于安裝,部署和使用。它基于Java,JDBC和SQL標(biāo)準(zhǔn)。它提供了一個(gè)嵌入式JDBC驅(qū)動(dòng)程序,可讓我們將Derby嵌入任何基于Java的解決方案中。它還通過(guò)Derby Network Client JDBC驅(qū)動(dòng)程序和Derby Network Server支持客戶(hù)機(jī)/服務(wù)器模式。
Spring Boot可以自動(dòng)配置嵌入式數(shù)據(jù)庫(kù),例如 H2,HSQL,和 Derbydatabases 。我們不需要提供任何連接URL。我們只需要包含要使用的嵌入式數(shù)據(jù)庫(kù)的構(gòu)建依賴(lài)項(xiàng)即可。
在Spring Boot中,只需在pom中添加 Derby 依賴(lài)項(xiàng)即可輕松集成Apache Derby數(shù)據(jù)庫(kù)。 xml文件。
<dependency> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> <scope>runtime</scope> </dependency>
步驟1: 打開(kāi)Spring Initializr https://start.spring.io/。
步驟2: 選擇最新版本的Spring Boot 2.3.0(SNAPSHOT)
步驟3: 提供Group名稱(chēng)。我們已經(jīng)提供了 com.nhooo。
步驟4: 提供Artifact ID。我們提供了 apache-derby-example 。
步驟5: 添加依賴(lài)項(xiàng): Spring Web,Spring Data JPA和 Apache Derby數(shù)據(jù)庫(kù)。
步驟6: 單擊 Generate (生成)按鈕。當(dāng)我們單擊"生成"按鈕時(shí),它會(huì)將項(xiàng)目包裝到一個(gè)Jar文件中,并將其下載到本地系統(tǒng)。
步驟7: 提取 Jar文件并將其粘貼到STS工作區(qū)中。
步驟8: 導(dǎo)入
文件->導(dǎo)入->現(xiàn)有Maven項(xiàng)目->瀏覽->選擇文件夾apache-derby-example->完成
導(dǎo)入需要一些時(shí)間。
步驟9: 在文件夾 src/main/java中創(chuàng)建一個(gè)名稱(chēng)為 com.nhooo.model 的包。
步驟10: 在包 com.nhooo.model 中創(chuàng)建一個(gè)名稱(chēng)為 UserRecord 的類(lèi),然后執(zhí)行以下:
定義三個(gè)變量 id, name, and email。生成Getter和Setter。
右鍵單擊文件-> Source-> Generate Getter和Setters 定義默認(rèn)的構(gòu)造函數(shù)。使用注解 @Entity將類(lèi)標(biāo)記為Entity。 使用注解 @Id將 Id 標(biāo)記為主鍵。
UserRecord.java
package com.nhooo.model; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class UserRecord { @Id private int id; private String name; private String email; //default conatructor public UserRecord() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
步驟11: 在 src/main/java文件夾中創(chuàng)建一個(gè)名稱(chēng)為 com.nhooo.controller 的包。
步驟12: 在包 com.nhooo.controller 中創(chuàng)建一個(gè)名稱(chēng)為 UserController 的Controller類(lèi),并執(zhí)行以下操作:
使用注解 @RestController 將類(lèi)標(biāo)記為控制器。使用注解 @Autowired 自動(dòng)連接類(lèi) UserService 。我們定義了兩個(gè)映射,一個(gè)映射用于獲取所有用戶(hù),另一個(gè)映射用于添加用戶(hù)。
UserController.java
package com.nhooo.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.nhooo.model.UserRecord; import com.nhooo.service.UserService; import java.util.List; @RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/") public List<UserRecord> getAllUser() { return userService.getAllUsers(); } @RequestMapping(value="/add-user", method=RequestMethod.POST) public void addUser(@RequestBody UserRecord userRecord) { userService.addUser(userRecord); } }
步驟13: 在文件夾 src/main/java中創(chuàng)建一個(gè)名稱(chēng)為 com.nhooo.service 的包。
步驟14: 在包 com.nhooo.service 中創(chuàng)建名稱(chēng)為 UserController 的Service類(lèi),并執(zhí)行以下操作:
通過(guò)使用注解 @Service將該類(lèi)標(biāo)記為服務(wù)。 自動(dòng)連接 UserRepository 定義方法 getAllUsers(),該方法返回以下列表: 定義另一個(gè)方法名稱(chēng) addUser(),以保存用戶(hù)記錄。
UserService.java
package com.nhooo.service; import java.util.List; import java.util.ArrayList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.nhooo.model.UserRecord; import com.nhooo.repository.UserRepository; @Service public class UserService { @Autowired private UserRepository userRepository; public List<UserRecord> getAllUsers() { List<UserRecord>userRecords = new ArrayList<>(); userRepository.findAll().forEach(userRecords::add); return userRecords; } public void addUser(UserRecord userRecord) { userRepository.save(userRecord); } }
步驟15: 在文件夾 src/main/java中創(chuàng)建一個(gè)名稱(chēng)為 com.nhooo.repository 的包。
步驟16: 在包 com.nhooo.repository 中創(chuàng)建名稱(chēng)為 UserRepository 的存儲(chǔ)庫(kù)接口,并擴(kuò)展 CrudRepository 。
UserRepository.java
package com.nhooo.repository; import org.springframework.data.repository.CrudRepository; import com.nhooo.model.UserRecord; public interface UserRepository extends CrudRepository<UserRecord, String> { }
步驟17: 現(xiàn)在,打開(kāi) ApacheDerbyExampleApplication.java 文件。它是在我們?cè)O(shè)置應(yīng)用程序時(shí)默認(rèn)創(chuàng)建的。
ApacheDerbyExampleApplication.java
package com.nhooo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ApacheDerbyExampleApplication { public static void main(String[] args) { SpringApplication.run(ApacheDerbyExampleApplication.class, args); } }
現(xiàn)在,我們已根據(jù)要求設(shè)置了所有必需的類(lèi)和程序包。請(qǐng)注意,我們沒(méi)有為數(shù)據(jù)庫(kù)提供任何連接URL 。完成上述所有步驟后,項(xiàng)目目錄如下所示:
讓我們運(yùn)行該應(yīng)用程序。
步驟18: 打開(kāi) ApacheDerbyExampleApplication.java 文件并將其作為Java應(yīng)用程序運(yùn)行。
第19步: 打開(kāi)瀏覽器并調(diào)用URL http://localhost:8080/。由于未在列表中添加任何用戶(hù),因此返回空列表。
要將用戶(hù)添加到數(shù)據(jù)庫(kù),我們將使用發(fā)送 POST 請(qǐng)求Postman。
步驟20: 打開(kāi)Postman,然后執(zhí)行以下操作:
選擇 POST 調(diào)用URL http://localhost:8080/add-user。點(diǎn)擊Body 選擇Content-Type作為JSON (application/json)。將要插入的數(shù)據(jù)插入數(shù)據(jù)庫(kù)中。我們插入了以下數(shù)據(jù):
{ "id": "001", "name": "Tom", "email": "tom@gmail.com" }
點(diǎn)擊發(fā)送按鈕。
當(dāng)我們單擊"發(fā)送"按鈕時(shí),它顯示狀態(tài): 200 OK 。這表示請(qǐng)求已成功執(zhí)行。
步驟21: 打開(kāi)瀏覽器并調(diào)用URL http: //localhost: 8080。它返回我們已插入數(shù)據(jù)庫(kù)中的用戶(hù)。