javascript
Spring Data JPA教程
在Java類或?qū)ο笈c關(guān)系數(shù)據(jù)庫之間管理數(shù)據(jù)是一項非常繁瑣且棘手的任務(wù)。 DAO層通常包含許多樣板代碼,應(yīng)簡化這些樣板代碼,以減少代碼行數(shù)并使代碼可重復(fù)使用。
在本教程中,我們將討論Spring數(shù)據(jù)的JPA實現(xiàn)。
1.簡介
1.1什么是JPA?
JPA或Java Persistence API是Java規(guī)范,用于訪問,管理和持久化Java類或?qū)ο笈c關(guān)系數(shù)據(jù)庫之間的數(shù)據(jù)。 該規(guī)范是EJB 3.0的一部分。
JPA不是實現(xiàn)或產(chǎn)品,它只是一個規(guī)范。 它包含需要實現(xiàn)的一組接口。 它是一個框架,為JPA實現(xiàn)提供了額外的抽象層。 存儲庫層將包含三層,如下所述。
- Spring Data JPA:–提供Spring數(shù)據(jù)存儲庫接口,這些接口可用于創(chuàng)建JPA存儲庫。
- Spring Data Commons:–它提供了在特定于數(shù)據(jù)存儲的spring數(shù)據(jù)項目之間共享的基礎(chǔ)結(jié)構(gòu)。
- 實現(xiàn)JPA持久性API的JPA提供程序。
Spring數(shù)據(jù)JPA允許我們不添加任何存儲庫層來編寫任何樣板代碼。
1.2 JPA的歷史
JPA2.0:– JPA2.0的開發(fā)始于2007年,名稱為JSR317。該版本被標(biāo)記為2.0,因為無法獲得1.0的共識。 重點(diǎn)是解決著名供應(yīng)商ORM所提供的功能。
JPA 2.1: -JPA2.1于2011年7月作為JSR 338開始。一些主要功能是實體圖,存儲過程,轉(zhuǎn)換器等。
JPA 2.2: -JPA2.2是2017年JPA系列的最新功能。它包括對Java 8日期和時間類型的支持以及流查詢結(jié)果的功能。
JPA仍在進(jìn)行大量更改,我們可以期待不久的JPA的更新版本。
1.3 Spring數(shù)據(jù)倉庫
Spring Data Commons項目提供了存儲庫抽象,該存儲庫抽象由特定于數(shù)據(jù)存儲的子項目擴(kuò)展。
我們必須熟悉Spring Data倉庫接口,因為它將幫助我們實現(xiàn)接口。 讓我們看一下接口。
Spring Data Commons:–作為該項目的一部分,提供了以下接口:
- Repository<T, ID extends Serializable> :此接口是標(biāo)記接口。
- 它捕獲托管實體的類型和實體ID的類型。
- 掃描類路徑時,它可以幫助Spring容器發(fā)現(xiàn)“具體的”存儲庫接口。
- CrudRepository<T, ID extends Serializable> :它為受管實體提供CRUD操作。
- PagingAndSortingRepository<T, ID extends Serializable> :此接口聲明用于對從數(shù)據(jù)庫中檢索到的實體進(jìn)行排序和分頁的方法。
- QueryDslPredicateExecutor<T> :它不是“存儲庫接口”。 它聲明使用QueryDsl 謂詞對象從數(shù)據(jù)庫檢索實體的方法。
Spring Data JPA:–該項目提供以下接口:
- JpaRepository<T, ID extends Serializable> :此接口是JPA特定的存儲庫接口,它將公共存儲庫接口聲明的方法組合在單個接口后面。
- JpaSpecificationExecutor<T> :再次不是“存儲庫接口”。 它聲明使用通過使用JPA標(biāo)準(zhǔn)API的Specification<T>對象從數(shù)據(jù)庫檢索實體的方法。
存儲庫層次結(jié)構(gòu)如下所示:
Spring數(shù)據(jù)存儲庫層次結(jié)構(gòu)
讓我們嘗試通過一個示例程序來了解Spring Data JPA。
1.4 Spring數(shù)據(jù)自定義查詢
讓我們考慮一個用例,其中我們必須基于查詢從數(shù)據(jù)庫中獲取數(shù)據(jù)。 編寫自定義查詢是非常有用的情況。 Spring Data JPA具有不同的編寫自定義查詢的方式。 我們將大致分類如下所述的方式。
自動自定義查詢:自動自定義查詢的創(chuàng)建也稱為從方法名稱查詢創(chuàng)建。 Spring Data JPA具有用于查詢創(chuàng)建的內(nèi)置機(jī)制,可用于直接從查詢方法的方法名稱解析查詢。 該機(jī)制首先從方法名稱中刪除公共前綴,并從其余方法名稱中解析查詢的約束。 為了使用這種方法,我們必須確保通過合并實體對象的屬性名稱和支持的關(guān)鍵字來創(chuàng)建存儲庫接口的方法名稱。
使用這種方法的優(yōu)點(diǎn)是它很容易實現(xiàn)。 但是限制是,如果查詢包含多個參數(shù),則方法名將不可讀。 同樣,JPA不支持的關(guān)鍵字(例如lower)也不適用于此方法。
手動自定義查詢:手動自定義查詢也稱為使用@Query標(biāo)記創(chuàng)建查詢。 @Query批注將用于使用JPA查詢語言創(chuàng)建查詢,并將這些查詢直接綁定到存儲庫接口的方法。 調(diào)用查詢方法時,Spring Data JPA將執(zhí)行@Query注釋指定的查詢。
這種方法的優(yōu)點(diǎn)是您可以使用JPA查詢語言來創(chuàng)建查詢。 此外,查詢?nèi)晕挥诖鎯鞂印?這種方法的局限性是@Query只能在支持JPA查詢語言時使用。
下面提到的程序使用這兩種方法。
1.5 Spring Data JPA異常轉(zhuǎn)換
需要考慮的重點(diǎn)是因為默認(rèn)的Spring ORM模板未與SPring JPA一起使用,是否通過使用Spring Data JPA丟失了異常轉(zhuǎn)換?是否不將JPA異常轉(zhuǎn)換為Spring的DataAccessException層次結(jié)構(gòu)?
答案是否定的 。 通過在DAO上使用@Repository批注,仍可以啟用異常轉(zhuǎn)換。 注釋使Spring Bean后處理器可以為所有@Repository Bean提供在Container中找到的所有PersistenceExceptionTranslator實例的建議,并像以前一樣提供異常轉(zhuǎn)換。
2.工具與技術(shù)
讓我們看看用于構(gòu)建程序的技術(shù)和工具。
- Eclipse Oxygen.2發(fā)布(4.7.2)
- Java –版本9.0.4
- Maven – 3.5.3
- Spring啟動– 2.0.1-發(fā)布
- PostgreSQL – 10
- 郵差
3.項目結(jié)構(gòu)
我們的項目結(jié)構(gòu)如下圖所示。
Spring Data JPA教程的項目結(jié)構(gòu)
上面的項目結(jié)構(gòu)使用的是Maven。 也可以使用Gradle創(chuàng)建該項目,并且pom.xml將替換為build.gradle文件。 該項目的結(jié)構(gòu)將稍微延遲使用Gradle進(jìn)行構(gòu)建。
4.方案目標(biāo)
作為程序的一部分,我們將嘗試使用spring boot創(chuàng)建一個簡單的Web服務(wù)。 該Web服務(wù)將用于PostgreSQL數(shù)據(jù)庫上的數(shù)據(jù)操作。
4.1 pom.xml
該程序的pom.xml文件如下所示。
使用Spring Boot的SpringData JPA的pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.springjpa</groupId><artifactId>SpringJPA-PostgreSQL</artifactId><version>0.0.1</version><packaging>jar</packaging><name>SpringJPA-PostgreSQL</name><description>Demo project for Spring Boot JPA - PostgreSQL</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.1.RELEASE</version><relativePath/> </parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.9</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.0</version> </dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>pom.xml文件將包含程序需要的依賴項。
4.2應(yīng)用類別
對我們來說,Application.java類是SpringJpaPostgreSqlApplication.java類。 該類如下所示。
Spring Boot的SpringJpaPostgreSqlApplication.java類
package com.tutorial;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;import com.tutorial.repo.EmployeeRepository;@SpringBootApplication public class SpringJpaPostgreSqlApplication implements CommandLineRunner{@AutowiredEmployeeRepository repository;public static void main(String[] args){SpringApplication.run(SpringJpaPostgreSqlApplication.class, args);}public void run(String... args) throws Exception {// TODO Auto-generated method stub}}CommandLineRunner接口用于指示當(dāng)bean包含在Spring Application中時應(yīng)運(yùn)行。
4.3模型類別
我們將創(chuàng)建一個Employee.java類作為模型類。 該類如下所示。
程序的模型類
package com.tutorial.model;import java.io.Serializable;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table;@Entity @Table(name = "employee") public class Employee implements Serializable {private static final long serialVersionUID = -3009157732242241606L;@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name="id")private long id;@Column(name = "firstname")private String firstName;@Column(name = "lastname")private String lastName;@Column(name = "age")private int age;protected Employee() {}public Employee(String firstName, String lastName,int age) {this.firstName = firstName;this.lastName = lastName;this.age = age;}@Overridepublic String toString() {return String.format("Employee[id=%d, firstName='%s', lastName='%s', age='%d']", id, firstName, lastName,age);}public long getId() {return id;}public void setId(long id) {this.id = id;}public String getFirstName() {return firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName;}public void setLast_Name(String lastName) {this.lastName = lastName;}public int getAge() {return age;}public void setAge(int age) {this.age = age;} } @Entity :用于定義該類為Entity類。
@Table :此批注用于指定數(shù)據(jù)庫中定義的表名。
@Id :Id注釋用于指定Id屬性 @GeneratedValue :當(dāng)我們要設(shè)置自動生成的值時使用。 GenerationType是用于生成特定列的值的機(jī)制。 @Column :此批注用于將表中的列與類中的屬性進(jìn)行映射。
4.4儲存庫接口
存儲庫接口用于擴(kuò)展CRUD接口。 該接口在程序中添加了存儲庫層。 Spring Data JPA提供了兩種創(chuàng)建查詢的主要方法。 然后,在存儲庫界面中使用這些查詢來從數(shù)據(jù)庫中獲取數(shù)據(jù)。
用于擴(kuò)展CRUD存儲庫的存儲庫類
package com.tutorial.repo;import java.util.List;import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository;import com.tutorial.model.Employee;@Repository public interface EmployeeRepository extends CrudRepository<Employee, Long>{List findByLastName(String lastName);@Query("SELECT e FROM Employee e WHERE e.age = :age")public List findByAge(@Param("age") int age); }CrudRepository是CrudRepository Common項目的接口。 上面提到的兩種用于查詢創(chuàng)建的方法在代碼的以下位置使用。
自動自定義查詢:
List findByLastName(String lastName);方法findByLastName包含姓氏作為參數(shù),將用于數(shù)據(jù)搜索。 另外,將使用JPA查詢構(gòu)建器自動創(chuàng)建查詢。
手動自定義查詢:
@Query("SELECT e FROM Employee e WHERE e.age = :age")public List findByAge(@Param("age") int age);在此方法中,我們手動定義了一個查詢以根據(jù)年齡取數(shù)據(jù),然后將查詢與findByAge方法綁定。
4.5屬性文件
作為用于連接數(shù)據(jù)庫的Spring Boot的一部分,我們將在屬性文件中提供詳細(xì)信息。 屬性文件如下所示。
Spring啟動的application.properties文件
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres spring.datasource.username=postgres spring.datasource.password=password spring.jpa.generate-ddl=true spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true作為屬性文件的一部分,提供了數(shù)據(jù)庫URL和憑據(jù)。 屬性spring.jpa.show-sql=true顯示JPA進(jìn)行數(shù)據(jù)操作期間生成的SQL查詢。
4.6控制器等級
控制器是整個程序中最重要的一類。 這是負(fù)責(zé)所有url映射的類。 我們在此類本身中添加了用于數(shù)據(jù)操作的存儲庫方法。
程序的控制器類
package com.tutorial.controller;import java.util.List; import java.util.Optional;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; 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.RequestParam; import org.springframework.web.bind.annotation.RestController;import com.tutorial.model.Employee; import com.tutorial.repo.EmployeeRepository;@RestController @RequestMapping("/employee") public class WebController {@AutowiredEmployeeRepository repository;@RequestMapping(value="/save",method = RequestMethod.POST)public HttpStatus insertEmployee(@RequestBody Employee employee){boolean status = repository.save(employee) != null; return status? HttpStatus.CREATED : HttpStatus.BAD_REQUEST;}@RequestMapping("/findall")public List findAll(){return (List) repository.findAll();}@RequestMapping("/findbyid")public Optional findById(@RequestParam("id") long id){Optional result = repository.findById(id);return result;}@RequestMapping("/findbylastname")public List fetchDataByLastName(@RequestParam("lastname") String lastName){return repository.findByLastName(lastName);}@RequestMapping("/findbyage")public List fetchDataByAge(@RequestParam("age") int age){return repository.findByAge(age);} } @RestController標(biāo)記用于將類定義為rest控制器類。
@RequestMapping標(biāo)記指定請求的路徑映射。 值屬性指定URL映射,方法屬性指定它的方法類型,例如GET,POST,PUT等。
如果默認(rèn)情況下不指定method屬性,則該方法被視為GET方法。
在此類中,我們已自動連接存儲庫,并使用界面中可用的方法進(jìn)行數(shù)據(jù)檢索,插入和刪除。
為了運(yùn)行spring boot應(yīng)用程序,我們必須提供命令spring-boot: run 。
5.輸出
下面提到的查詢可用于在PostgreSQL中創(chuàng)建Employee表。
用于查詢Employee表的SQL查詢
create table employee ( id serial not null primary key, firstName varchar(20) not null, lastName varchar(20) not null, age integer not null );讓我們檢查數(shù)據(jù)庫中可用的數(shù)據(jù)。 數(shù)據(jù)庫中的當(dāng)前可用數(shù)據(jù)如下所示。
PostgreSQL中的數(shù)據(jù)
現(xiàn)在,讓我們嘗試使用postman集合來查找findall API,以獲取結(jié)果行。 結(jié)果將如下所示在郵遞員上。
Findall API在郵遞員上的結(jié)果
為了在數(shù)據(jù)庫中添加一些雇員對象。 我們將使用save API并將傳遞一個employee對象。
使用保存API將對象存儲在DB中
讓我們檢查數(shù)據(jù)庫中保存API的用法。 該數(shù)據(jù)庫將如下所示。
使用Save API保存數(shù)據(jù)后
同樣,我們可以使用findbylastname API來查找具有request參數(shù)中提供的姓氏的記錄。
findbylastname API的結(jié)果
讓我們看看綁定到手動自定義查詢的方法的結(jié)果。
findByAge API的結(jié)果
6.總結(jié)
本教程的摘要在下面提到。
7.下載Eclipse項目
這是使用SpringBoot的SpringData JPA教程。
您可以在此處下載此示例的完整源代碼: SpringJPA-PostgreSQL.zip翻譯自: https://www.javacodegeeks.com/2018/05/spring-data-jpa-tutorial.html
總結(jié)
以上是生活随笔為你收集整理的Spring Data JPA教程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 柞树的读音 柞树念啥呢
- 下一篇: 在Spring MVC中处理域对象