大家好,我是 "為了拿到金角獎盃而努力著" 的文毅青年 - Kai
If you can't make it good, at least make it look good.
上週已經提完了關於 JPA、ORM、Spring Data & JPA 的部分。
這週就來做一個簡單的實作範例。
如何透過 Entity、Repository 的方式掌控著以往使用 DAO 處理 DB 的方式。
延續前幾週的範例方式,Kai 全部都實作在同一個專案中,有興趣的人可以私信我分享。
Image Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
}
在 dependencies 加入 spring data jpa 的套件,並還有使用 H2 DB 作為範例DB使用。
有興趣的人可以研究一下 H2 DB,他是一個非常輕量版,幾乎只需要使用套件即可運行,不需要任何安裝動作的 DB
Kai 建立一個屬於員工的 Entity 作為示範範例
package kai.com.jpa.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.sql.Date;
@Entity
public class Employee {
public Employee (){}
public Employee(String name, String team, Date birthDate){
this.emp_name = name;
this.emp_team = team;
this.emp_birthDate = birthDate;
}
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long emp_id;
private String emp_name;
private String emp_team;
private Date emp_birthDate;
public Long getEmp_id() {
return emp_id;
}
public void setEmp_id(Long emp_id) {
this.emp_id = emp_id;
}
public String getEmp_name() {
return emp_name;
}
public void setEmp_name(String emp_name) {
this.emp_name = emp_name;
}
public String getEmp_team() {
return emp_team;
}
public void setEmp_team(String emp_team) {
this.emp_team = emp_team;
}
public Date getEmp_birthDate() {
return emp_birthDate;
}
public void setEmp_birthDate(Date emp_birthdate) {
this.emp_birthDate = emp_birthdate;
}
}
package kai.com.jpa.repository;
import kai.com.jpa.entity.Employee;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
import java.util.Optional;
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
List<Employee> findAll();
Optional<Employee> findById(Long id);
void deleteById(Long id);
@Query(value="SELECT * FROM EMPLOYEE as e WHERE e.EMP_ID BETWEEN ?1 AND ?2 " ,nativeQuery = true)
List<Employee> findByPriorityBetween(Long number1, Long number2);
}
因為需要一些資料當作測試用,因此有多寫一支 API 專門用來建立資料這樣,其實也可以透過 Class build 起來時就直接建立好。
不過為了當作範例,就想說必須要有明確地做點什麼。
package kai.com.jpa.controller;
import kai.com.jpa.entity.Employee;
import kai.com.jpa.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.sql.Date;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/getEmp")
public class JPATestController {
@Autowired
EmployeeRepository employeeRepository;
@GetMapping("/build")
public String buildTableAndData(){
/*** 建立測試資料 ***/
Employee emp = new Employee();
emp.setEmp_name("Michael");
emp.setEmp_team("IT");
emp.setEmp_birthDate(new Date(19920101));
employeeRepository.save(emp);
emp = new Employee();
emp.setEmp_name("Cherry");
emp.setEmp_team("Salse");
emp.setEmp_birthDate(new Date(19900101));
employeeRepository.save(emp);
emp = new Employee();
emp.setEmp_name("Stanley");
emp.setEmp_team("Product");
emp.setEmp_birthDate(new Date(19960101));
employeeRepository.save(emp);
return "Done build.";
}
@GetMapping()
public List<Employee> getAll(){
return employeeRepository.findAll();
}
@GetMapping("/{number1}/{number2}")
public List<Employee> getByRange(@PathVariable("number1") Long number1, @PathVariable("number2") Long number2){
return employeeRepository.findByPriorityBetween(number1,number2);
}
@GetMapping("/{id}")
public Optional<Employee> getById(@PathVariable("id") Long Id){
return employeeRepository.findById(Id);
}
@DeleteMapping("/{id}")
public String deleteById(@PathVariable("id") Long Id){
employeeRepository.deleteById(Id);
if(!employeeRepository.findById(Id).isPresent())
return "Delete Successfully.";
return "Delete failed.";
}
}
建立測試用的資料
搜尋全部人的資料
搜尋 ID 為 1 的單筆資料
搜尋 ID 為 1 到 2 的範圍資料
刪除 ID 為 1 的單筆資料
再查詢全部後會發現少了 ID 為 1 的資料
另外提一點是,這邊 Kai 的設計方法做的差了,實際應用上的取資料路徑盡量避免與處理 update 和 delete 的路徑一樣
這篇算是簡單的給出了一個應用上的範例,我們可以看到透過 Repository 的方式,少寫了非常多的 DAO class,以及不會因為少了 DAO 就無法進行客製化的動作,Repository 的 QUERY 提供了 JPQL 超級多的作法以滿足開發者的需求!
詳細的可以參閱 Kai 找到的一篇整理非常詳細的 @Query 應用文章
Spring Data JPA Custom Queries using @Query Annotation
希望這兩篇關於 JPA 的文章可以帶給尚未嘗試使用 JPA 的朋友們一點了解~
下一篇來介紹 @Query 比較細節的部分
六角鼠年鐵人賽 Week 27 - Spring Boot - Spring Data & JPA @Query Annotation
Spring Boot
,Spring Data
,w3HexSchool