iT邦幫忙

2024 iThome 鐵人賽

DAY 12
1
佛心分享-SideProject30

從卡關到通關的Spring Boot 腦內風暴系列 第 12

解密 Spring Data JPA—Repository (補充專案結構)

  • 分享至 

  • xImage
  •  

採用Spring開發時,可透過Spring Data JPA進行資料存取,藉此不用撰寫繁瑣的SQL或直接操作資料庫。
JPA可參考先前寫的文章 誤會大了–JPA不是ORM框架
此篇介紹Spring Data JPA提供的Repository介面操作,可以直接使用內建方法完成基本的資料庫操作。在此之前先介紹Spring Boot的專案結構,有助於了解Repository在這之間扮演的角色。

Spring Boot專案結構

Spring Boot的專案,建議可採分層架構,日後維護會比較容易,也能夠提高擴展性:

src/
└── main/
    ├── java/
    │   └── com.example.project/
    │       ├── controller/      # Controller層,處理HTTP請求並回應
    │       ├── service/         # Service層,處理業務邏輯
    │       ├── repository/      # Repository層,與資料庫互動
    │       ├── model/           # Model層,像是Entity資料庫實體類別
    │       └── Application.java # Spring Boot的應用程式入口
    └── resources/
        ├── application.yml        # Spring Boot的配置文件
        └── templates/             # Thymeleaf模板,若未採前後端分離,可將模板放於此

Repository

  • Repository介面
public interface TaskRepository extends JpaRepository<Task, Long> {
}
// 繼承JpaRepository,並給予泛型:<實體對象類, ID類型> 
  • Repository子介面
    以下介紹常用的子介面功能:
CrudRepository<T, ID>:基本增刪查改功能

// 儲存或更新實體 save(S entity)
Task task = new Task();
taskRepository.save(task);
 
// 根據ID查詢實體 findById(ID id) 
Task task = taskRepository.findById(1L).orElse(null);
if (task != null) {
    System.out.println(task.getName());
}

// 查詢所有該實體 findAll() 
taskRepository.findAll().forEach(task -> System.out.println(task.getName()));

// 根據ID刪除實體 deleteById(ID id)
taskRepository.deleteById(1L);

  • 自動查詢
    若要查詢進階操作,可根據命名規則進行自動生成查詢:
List<Task> findByStatus(String status);
// 上述會被映射為以下 SQL 查詢
SELECT * FROM task WHERE status = ?

上述命名規則可以使我們不用手動撰寫SQL查詢。

  • 自定義查詢
    若要進行更複雜的操作,可直接使用@Query註解,撰寫JPQL或原生SQL查詢:(幫我修改簡單點的例子)
@Query("SELECT t FROM Task t WHERE t.assignedUser = ?1")
List<Task> findByAssignedUser(String username);

// 上述查詢將映射為以下SQL查詢
SELECT * FROM task WHERE assigned_user = ?1;

若不使用Spring直接處理DB存取

假設直接使用JDBC操作DB,程式碼會變得冗長,且還要在該程式內手動管理DB連線與處理結果:

    private static final String URL = "jdbc:mysql://localhost:3306/yourdatabase";
    private static final String USER = "root";
    private static final String PASSWORD = "password";
    
    // 根據ID查詢實體
    public Task findById(Long id) {
        Task task = null;
        String query = "SELECT * FROM task WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             PreparedStatement stmt = conn.prepareStatement(query)) {
             
            stmt.setLong(1, id);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                task = new Task(rs.getLong("id"), rs.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return task;
    }

    // 查詢所有實體
    public List<Task> findAll() {
        List<Task> tasks = new ArrayList<>();
        String query = "SELECT * FROM task";
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {
             while (rs.next()) {
                tasks.add(new Task(rs.getLong("id"), rs.getString("name")));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return tasks;
    }

由上述例子可清楚知道,Spring Data JPA的Repository介面簡化資料存取工作,不只提供基礎的資料庫操作功能,也能靈活查詢應用,可讀性及維護性大大的提升。我們只要專注於業務邏輯即可,不用花費額外時間撰寫繁瑣的資料存取操作。

同時補充,Spring Data JPA是Spring框架的功能,並非Spring Boot專有的,不過正如前幾篇所說,Spring Boot能整合大量配置使其自動化,因此,在Spring Boot專案中不需要手動做很多配置,若只是使用Spring框架,仍需額外配置像是EntityManager、資料庫連線、Transaction管理等。


上一篇
沒有要給你知道那麼多—DTO 設計應用
下一篇
我傳我傳我傳傳傳—前端請求參數傳入方式
系列文
從卡關到通關的Spring Boot 腦內風暴30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言