iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
3
Modern Web

站在Web前端人員角度,學習 Spring Boot 後端開發系列 第 8

Day 08 - Spring Boot JPA 與 Lombok 套件 & DAO

先解決眼前的難題,然後等待,讓時間替你解決! -- 《舉重妖精金福珠》

上一篇我們會發現,當我們要建立實體(Entity)時,必須將屬性增加 getter & setter 方法,而程式碼會導致存在許多 getterr 與 setter,此時我們就可以使用 Java Library- Lombok,它的誕生主要是希望幫助我們大幅減少 Java 實務開發上會有許多 getter 與 setter 的問題,讓我們不用再一直寫getter、setter,只要在類別上使用 @Getter @Setter Annotation 標註即可。

安裝Lombok

(1)在pom.xml添加dependency Lombok官方文件

<dependencies>
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.18.12</version>
		<scope>provided</scope>
	</dependency>
</dependencies>

(2)還要要安裝 Intellij lombok 插件,是因為如果不安裝 lombok plugin的話,Intellij 就會沒辦法自動提示出 lombok 產生的方法,所以就會發生 code 一片紅。->Lombok plugin

Lombok 用法

@Getter/@Setter,簡化重複的Getters / Setters構造函數

原本寫法

import javax.persistence.*;

@Entity
@Table
public class Todo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;

    @Column
    String task;

    @Column
    Integer status;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTask() {
        return task;
    }

    public void setTask(String task) {
        this.task = task;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }
}

可以聲明@Getter @Setter 為此類的屬性自動產生Get/ Set方法

package com.caili.todolist.entity;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Table
@Getter @Setter
@NoArgsConstructor
public class Todo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Integer id;

    @Column
    String task;

    @Column
    Integer status;
}

@ToString

原本寫法

import javax.persistence.*;

   /**
    * @author cai-li
    */
   @Entity
   @Table
   public class Todo {
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       Integer id;

       @Column
       String task;

       @Column
       Integer status;

       @Override
       public String toString() {
           return "Todo{" +
                   "id=" + id +
                   ", task='" + task + '\'' +
                   ", status=" + status +
                   '}';
       }
 }

使用@ToString後

@Entity
@Table
@ToString
public class Todo {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   Integer id;

   @Column
   String task;

   @Column
   Integer status;
   
}

JPA(Java Persistence API)

JPA為Java Persistence API的簡寫,它是官方提出的ORM規範,也是一個 Java 應用程式的介面,利用標註 Annotation 的方式或XML描述物件與關係表的對應關係,import 套件時的package路徑為 javax.persistence.*,常見如:@Entity、@Table、@Column、@Transient等標註 Annotation。

但JPA只是一個介面,需要實現它,而 Hibernate就是實現了JPA介面的ORM框架。

Spring Data JPA

為 Spring 基於ORM框架、JPA規範封裝的一套JPA應用框架,底層使用了Hibernate,可以使開發者用簡單的程式碼實現對資料庫溝通與操作,包含了新增、修改、刪除等易於我們進行其他方法擴充,我們這次是Spring Data JPA 來簡化JPA的實現並對資料庫進行溝通與操作。

Data Access Object (DAO)

資料存取物件(Data Access Object, DAO)是為了讓我們在開發專案時,處理資料庫相關操作更方便而產生的物件,它會幫助我們封裝資料庫進行持久層的操作,我們會在 DAO 層提供一些特定的資料操作,不需要直接暴露資料庫細節。

Spring Data JPA 有提供以下Interface

  • Repository 最頂層的介面
  • CrudRepository 是Repository的子介面,提供CRUD的功能
  • PagingAndSortingRepository 是CrudRepository的子介面,添加分頁和排序的功能
  • JpaRepository 是PagingAndSortingRepository的子介面

方法命名

方法命名規則進行相關資料庫操作,簡化程式碼。

https://ithelp.ithome.com.tw/upload/images/20200917/20118857Bo0oKO5jMj.png

繼承CrudRepository interface 實作DAO

(1)在src → main → java → com.xxx..xxx → dao 建立一個名為TodoDao.java 的interface,並且繼承CrudRepositoryCrudRepository文件,裡面有提供操作資料庫的方法。

|-- src
    |-- main
        |-- java
             |-- com.xxx.xxxxx
                  |-- entity
                    |-- Todo.java
                  |-- dao
                    |-- TodoDao.java
                  |-- TodoListApplication.java # 程式進入點

https://ithelp.ithome.com.tw/upload/images/20200917/20118857yPvYhQgfkf.png
(2) TodoDao.java 創造TodoDao就可以用DAO 去操作資料庫了。

import com.caili.todolist.entity.Todo;
import org.springframework.data.repository.CrudRepository;

// 第一個參數為訪問的實體,第二參數是這個Entity ID的資料型態
public interface TodoDao extends CrudRepository<Todo, Integer> {

}

我在實作DAO時候有遇到一個問題,用TodoDao 去繼承一個CrudRepository的介面,卻不用implement它的方法,就可以直接使用TodoDao 去操作資料庫物件,如下。

@Service
public class TodoService {
    @Autowired
    TodoDao todoDao;

    public Iterable<Todo> getTodo() {
        return todoDao.findAll();
    }
}

而stackoverflow也有人相同疑問(https://stackoverflow.com/questions/58881221/why-do-we-extend-jparepository-interface-and-not-implements-it )
是因為TodoDao將在運行時基於SimpleJpaRepository從Spring Data JPA實現,從內部文件來看,CrudRepository 已經有繼承一個SimpleJpaRepository 的class,而這個class已經有實作一些方法了,可以至SimpleJpaRepository 看更詳細的文件。
https://ithelp.ithome.com.tw/upload/images/20200917/20118857VONvbJJfJP.png


上一篇
Day 07 - Spring Boot 資料庫 H2 + Entity
下一篇
Day 09 - Spring Boot 基礎單元測試
系列文
站在Web前端人員角度,學習 Spring Boot 後端開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言