選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
4 分鐘閱讀時間 (732 個字)

Spring Data JPA

front-view-mockup-of-macbook-pro-with-a-library

前言

實作一個基本資料庫存取功能的程式,需要寫大量的程式做資料庫的連接,甚至還需了解不同資料庫的語法,才能看到功能的雛形,而每多一個功能也需要做許多重複的事情。此篇介紹 Spring Data JPA 可以大幅降低資料庫存取功能的工作,讓開發人員更專注在商業邏輯上。

JPA 是什麼?

JPA(Java Persistence API) 是 SUN 針對 ORM 技術提出的規範,目的為簡化持久化的開發工作以及整合各家 ORM 技術(Hibernate、TopLink、OpenJpa…)。

Spring Data JPA

Spring Data JPA 是 Spring 根據 ORM 框架和 JPA 規範而封裝的 JPA 應用框架,目的是降低存取資料層的工作量,讓開發人員只需寫出 repository 的介面,而 Spring 自動幫你實作其功能。

JpaRepository interface

PagingAndSortingRepository

public interface JpaRepository<T,ID>
extends PagingAndSortingRepository<T,ID>, QueryByExampleExecutor

SIMPLEJPAREPOSITORY

SimpleJpaRepository 中有實作 JpaRepository 介面,實作內容包含簡單的 crud,包含 count()existsById(ID id)findAll(Specification<T> spec, Pageable pageable) 等等,當繼承 JpaRepository 後不必實作上述方法也能使用。

使用方法

MAVEN

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>
 

GRADLE

compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.2.6.RELEASE'

ENTITY

建立 Entity 達成 orm

@Data
@Entity
@EntityListeners(AuditingEntityListener.class)
public class User {

  @Id
  @GeneratedValue
  private long id;
  private String name;
  @ManyToOne
  private Country country;
  private int age;
  @CreatedDate
  private LocalDateTime createdDate;
}
  

可用的 Annotation

  • @Entity 是告訴 Spring 這是資料模型層的宣告。
  • @Table 對應到資料庫中的名稱,也可指定要建立的 index。
  • @Column 對應到 Table 的欄位中的欄位名稱。
  • @Id 此資料表的 Primary Key。
  • @GeneratedValue 告訴此Column的生成方式 ,如果設定成 GenerationType.AUTO 讓容器來自動產生。
  • @CreatedDate 在 Entity 被建立或修改時會自動賦值。
  • @ManyToOne@OneToMany 相當於資料表中 FOREIGN KEY 設定
    • CascadeType.PERSIST 在儲存時一併儲存被參考的物件。
    • CascadeType.MERGE 在合併修改時一併合併修改被參考的物件。
    • CascadeType.REMOVE 在移除時一併移除被參考的物件。
    • CascadeType.REFRESH 在更新時一併更新被參考的物件。
    • CascadeType.ALL 無論儲存、合併、更新或移除,一併對被參考物件作出對應動作。

DAO

建立 UserDao 繼承 JpaRepository

@Repository
public interface UserDao extends JpaRepository<User, Integer> {
    List<User> findByCountryAndAgeLessThan(Country country, int age);
}

 

自定義 METHOD 規則

KeywordSampleSQL
And findByNameAndCountry …WHERE name = ?1 AND country =?2
Between findByAgeBetween …WHERE age <= ?1 AND age >=?2
LessThan findByAgeLessThan …WHERE age < ?1
Like findByNameLike …WHERE name LIKE ?1

特殊用法

Page<User> findByName(String name, Pageable pageable);
List<User> findByName(String name, Sort sort);

public void findUser() {
    int page = 0;
    int size = 10;
    Sort sort = new Sort(Direction.DESC, "age");
    Pageable pageable = new PageRequest(page, size, sort);
    Page<User> page = userDao.findAll(pageable);
    Page<User> page = userDao.findByCountry(country, pageable);
}
 

自行寫 SQL

@Query(value="select * from user where name like %?1", nativeQuery=true)
public List<User> findByName(String name);

 

Spring Data JPA - JpaRepository 原理

問題一

  • 為什麼不需要 implement 就可以完成 CRUD?

呼叫流程

  1. 透過 @EnableJpaRepositories import JpaRepositoriesRegistrar
  2. JpaRepositoriesRegistrar 繼承於 RepositoryBeanDefinitionRegistrarSupport
  3. RepositoryBeanDefinitionRegistrarSupport 的 registerBeanDefinitions 向 spring 註冊 JpaRepositoryFactoryBean
  4. JpaRepositoryFactoryBean.afterPropertiesSet() 會調用 RepositoryFactorySupport.getRepository()
  5. JpaRepositoryFactory 繼承 RepositoryFactorySupport 並且預設的 repository 為 SimpleJpaRepository
  6. 所以繼承 JpaRepository 的 class 不需要實作就可以完成 CRUD 的功能。

問題二

  • SimpleJpaRepository 沒有實作的功能(ex findByName(String name)),為什麼也能存取 DB。

原因

  1. 在問題一的 RepositoryFactorySupport.getRepository() 中會調用 QueryExecutorMethodInterceptor,此攔截器就是拿來判斷 method 的類型。
  2. findByName() 的類型是自定義的查詢,所以會跑到 SingleEntityExecution()
  3. 繼續往下追會發現底層使用 hibernate 的 CriteriaQueryImpl 來拼湊出 sql。

總結

使用 JpaRepository 的好處:

  • 減少開發時間
  • 增加程式可讀性

參考資料

Spring Data JPA - Reference Documentation
SpringDataJpa: JpaRepository增删改查
Spring Data JPA 之 JpaRepository
CascadeType 與 FetchType
【spring boot 系列】spring data jpa 全面解析(实践 + 源码分析)
[Java] JPA 是什麼?

 
 
使用 Sqlkata 產生 SQL Statement
淺談ITIL 4 與服務管理實踐

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/05/04, 週六

Captcha 圖像