在本教程中,優銳課小U將帶大家看到Spring Data JPA如何在DAO層上提供完整的抽象。我們不再需要爲DAO層編寫實現; Spring Data自動生成實現DAO實現。
依賴配置
在本教程中,我將MySQL數據庫與Spring Data一起使用。 這是build.gradle文件:
buildscript {
ext {
springBootVersion = '2.1.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.amitph.spring'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile('mysql:mysql-connector-java:8.0.13')
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
數據源配置
現在,我們已經配置了依賴項。現在還不該告訴要連接到哪個數據源。這是我的帶有Spring Boot數據源條目的application.yml。
spring:
datasource:
url: jdbc:mysql://localhost:33099/dogs
password: <ENTER _ PASSWORD _ HERE >
username: root
driver-class-name: "com.mysql.jdbc.Driver"
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: update
在這裏,我們具有指定的JDBC URL,用戶名,密碼和驅動程序類名稱(MySQL)。
除此之外,還有JPA特定的配置。首先是數據庫平臺,它告訴我們在MySQL查詢方言下要考慮的基礎Hibernate功能。這樣,所有數據庫操作將以MySQL特定的語法處理。第二個JPA配置是ddl-auto,它告訴Hibernate創建各自的數據庫和表結構(如果尚未存在的話)。
啓用此選項後,Hibernate將基於實體Bean和數據源創建數據庫結構。
Entity Bean
我們將要做的第一級代碼是編寫一個Entity Bean。這是Oracle文檔關於實體Bean的內容。
使用JPA,你可以將任何POJO類指定爲JPA實體——使用從JPA持久性提供程序(在Java EE EJB容器內或外部)獲得的實體管理器的服務,其非瞬態字段應持久保存到關係數據庫的Java對象。Java SE應用程序中的EJB容器)。
用簡單的話來說,JPA實體是任何Java POJO,都可以表示基礎表結構。由於我們的服務基於“Dog
”表,因此我們將創建一個“Dog
” 實體對象。
package com.amitph.spring.dogs.repo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Dog {
@Id
@GeneratedValue
private long id;
private String name;
private int age;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
上面的POJO用@Entity
註釋,表示這是表名Dog的實體對象。
然後,有三個字段代表數據表列。字段ID是我們的主鍵,因此被標記爲@Id。
字段ID也用@GeneratedValue
標記,表示這是一個自動增量列,Hibernate將負責輸入下一個值。Hibernate首先將查詢基礎表以瞭解該列的最大值,並在下一次插入時對其進行遞增。這也意味着我們不需要爲Id列指定任何值,可以將其留空。
倉庫接口
存儲庫代表DAO層,通常執行所有數據庫操作。感謝Spring Data,他提供了這些方法的實現。讓我們看看我們的DogsRepoisitory
,它擴展了CrudRepository
:
package com.amitph.spring.dogs.repo;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DogsRepository extends CrudRepository<Dog, Long> {}
DogsRepository
中這裏沒有方法聲明。這是因爲Spring Data的CrudInterface
已經聲明瞭基本的CRUD方法。
在這裏,我們完成了JPA和Spring數據工作——換句話說,就是DAO層。現在,讓我們編寫一個簡單的服務層和一個控制器。
控制器和服務層
完成數據訪問層後,我們將編寫控制器和服務層。請注意,DogsRepository
帶有@Repository
註釋,這也將其添加到Spring Context中。現在,我們可以在Service
中自動連線存儲庫。
Dogs Service
此類具有簡單的CRUD方法。還將Entity Bean轉換爲DTO(數據傳輸對象)。DTO還是一個簡單的Java POJO,用於在系統之間傳輸數據。在這裏,我們從REST端點返回DTO。
package com.amitph.spring.dogs.service;
import com.amitph.spring.dogs.model.DogDto;
import com.amitph.spring.dogs.repo.Dog;
import com.amitph.spring.dogs.repo.DogsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
public class DogsService {
@Autowired DogsRepository repository;
public void add(DogDto dto) {
repository.save(toEntity(dto));
}
public void delete(long id) {
repository.deleteById(id);
}
public List<Dog> getDogs() {
return (List<Dog>) repository.findAll();
}
public Dog getDogById(long id) {
Optional<Dog> optionalDog = repository.findById(id);
return optionalDog.orElseThrow(() -> new DogNotFoundException("Couldn't find a Dog with id: " + id));
}
private Dog toEntity(DogDto dto) {
Dog entity = new Dog();
entity.setName(dto.getName());
entity.setAge(dto.getAge());
return entity;
}
}
Dogs控制器
Dogs Controller是具有簡單CRUD端點的標準REST控制器。控制器的工作是處理HTTP請求並調用Service類方法。
package com.amitph.spring.dogs.web;
import com.amitph.spring.dogs.model.DogDto;
import com.amitph.spring.dogs.repo.Dog;
import com.amitph.spring.dogs.service.DogsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/dogs")
public class DogsController {
@Autowired DogsService service;
@GetMapping
public List<Dog> getDogs() {
return service.getDogs();
}
@PostMapping
public void postDogs(@RequestBody DogDto dto) {
service.add(dto);
}
@GetMapping("/{id}")
public Dog getById(@PathVariable(required = true) long id) {
return service.getDogById(id);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable(required = true) long id) {
service.delete(id);
}
}
現在,Dogs Service已準備好運行。啓動應用程序並執行HTTP端點。
結論
Spring數據和JPA教程的Spring Boot到此結束。我們看到了如何將Spring Data的抽象用於數據訪問層。我們看到了如何以Entity Bean的形式表示數據庫表,以及如何使用Spring Data的自動生成的存儲庫實現。此外,我們還看到了如何使用Spring Boot進行自動數據源配置。
在Spring Boot Rest Service帖子中,我們已經看到了使用Spring Boot創建RESTful Web服務。在當前文章中,我們不關心異常處理。訪問Spring Rest Service異常處理以瞭解有關處理異常的信息。我們還跳過了這裏的單元測試部分,這將在以後的文章中介紹。