如果你想讓你的應用程式能夠儲存和讀取資料,那麼 Spring Data JPA 絕對是你需要認識的好夥伴。今天內容將用最簡單的方式,來了解什麼是 JPA,並學會如何設定開發和生產環境的資料庫。
在開始之前,我們先來初步了解 JPA (Java Persistence API)。
想像一下,在 Java 程式中,我們操作的是「物件」(Object),例如一個 User
物件,它有 id
、name
、email
等屬性。但在資料庫中,我們儲存的是「資料列」(Row),例如 users
資料表中的一筆紀錄,它有 id
、name
、email
等欄位。這兩者結構不同,直接溝通起來很麻煩。
傳統上,我們需要手動編寫一堆稱為 JDBC 的程式碼,把物件的屬性一個個取出來,組合成 SQL 語法,再存入資料庫。反過來,也要手動把資料庫的欄位一個個讀出來,再放回物件裡。這個過程不僅程式碼冗長、重複,而且只要 SQL 語法有任何微小變動,就必須修改 Java 程式碼。當應用程式規模變大時,維護成本會變得非常高且容易出錯。
ORM 與 JPA 的誕生
為了解決這個問題,ORM (Object-Relational Mapping, 物件關聯對映) 的概念應運而生。ORM 就像一個專業的自動翻譯機,它能自動幫我們把 Java 物件「對映」到資料庫的資料表,讓我們可以用操作物件的方式,間接操作資料庫。
// 使用 JPA 後,儲存一個使用者可能只需要這樣一行程式碼
userRepository.save(newUser);
而 JPA 正是 Java 官方為 ORM 制定的一套「標準規範」或「介面」。它只定義了規則(例如:你應該用 @Entity
標註一個物件,用 @Id
標註主鍵),但不提供具體的實現方法。
這就好比 JPA 是一份建築藍圖,它規定了房子要有門、有窗戶,但沒有說明要用什麼材料蓋。Hibernate 就是業界最知名的「建築公司」之一,它根據 JPA 這份藍圖,提供了完整且強大的實作。
使用 JPA 的好處:
Spring Data JPA 則是 Spring 家族的一員,它在 JPA 的基礎上又做了一層抽象和簡化。它提供了一系列強大的 Repository 介面,我們甚至不需要寫任何實作類別,就能自動獲得 CRUD(新增、讀取、更新、刪除)等常用功能,讓我們可以用更少量的程式碼來完成資料庫操作,來提升開發效率極致。
有時候對於剛開始開發或進行單元測試的階段,我們不希望每次都得啟動一個完整的資料庫系統。這時候,H2 就是我們的最佳選擇。
什麼是 H2?
H2 是一個用 Java 編寫的輕量級「記憶體中資料庫」(In-Memory Database)。它的特點是:
設定步驟
第一步:加入依賴 (Dependency)
在你的 pom.xml
檔案中,確認有加入 spring-boot-starter-data-jpa
和 h2
的依賴 (Dependency)。
<dependencies>
<!-- Spring Data JPA 核心依賴,它會自動引入 JPA API 和 Hibernate 等相關套件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 資料庫依賴 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<!-- scope 設定為 runtime 表示這個依賴在編譯時期不需要,只在執行時期需要 -->
<scope>runtime</scope>
</dependency>
</dependencies>
第二步:設定 application.properties
在 src/main/resources/application.properties
檔案中加入以下設定。Spring Boot 會偵測到 H2 在 classpath 中,並自動進行大部分的設定,但我們可以覆寫這些設定以符合我們的需求。
# --- H2 資料庫設定 ---
# 啟用 H2 Console,這是一個內建的網頁管理介面,非常適合在開發時查看資料庫狀態
spring.h2.console.enabled=true
# 設定 H2 Console 的路徑,預設就是 /h2-console
spring.h2.console.path=/h2-console
# 資料庫連線 URL。'jdbc:h2:mem:testdb' 的意思是:
# jdbc:h2 -> 使用 H2 資料庫
# mem -> 資料庫模式為記憶體模式
# testdb -> 資料庫的名稱是 testdb
spring.datasource.url=jdbc:h2:mem:testdb
# 資料庫驅動程式的類別名稱,Spring Boot 通常會自動偵測,但明確寫出是個好習慣
spring.datasource.driverClassName=org.h2.Driver
# 登入資料庫的預設帳號和密碼
spring.datasource.username=sa
spring.datasource.password=
# 告訴 Hibernate 我們正在使用 H2 資料庫的 SQL 方言 (Dialect)
# 方言能讓 Hibernate 產生針對特定資料庫優化的 SQL 語法
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
第三步:啟動並測試
現在啟動你的 Spring Boot 應用程式。啟動完成後,打開瀏覽器,前往 http://localhost:8080/h2-console
。
你會看到一個登入頁面。請務必確認 JDBC URL 欄位的值與你在 application.properties
中設定的 jdbc:h2:mem:testdb
完全一致。如果不同,請手動修改,然後點擊「Connect」。如果成功,你就可以看到資料庫的管理介面了,即使目前裡面還沒有任何資料表。
當你的應用程式準備要部署到測試或正式環境時,就需要一個能夠永久儲存資料的資料庫,例如:PostgreSQL。PostgreSQL 是一個功能強大、穩定且開源的關聯式資料庫,被廣泛應用於各種規模的專案中。
假設你已經在你的電腦或伺服器上安裝好了 PostgreSQL,並使用 psql
或 pgAdmin
等工具建立了一個空的資料庫。
設定步驟
第一步:加入依賴 (Dependency)
首先,我們需要 PostgreSQL 的 JDBC 驅動程式,它負責讓我們的 Java 應用程式能與 PostgreSQL 資料庫溝通。在 pom.xml
中加入以下依賴(你也可以同時保留 H2 的依賴,以便在不同環境切換使用)。
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.7</version>
<scope>runtime</scope>
</dependency>
第二步:修改 application.properties
現在,我們將資料庫連線設定從 H2 改成 PostgreSQL。你可以先把 H2 的設定註解 (Comment) 掉(在每一行前面加上 #
),或是使用 Spring Profiles 來管理不同環境的設定(這是更進階也更推薦的做法)。
# --- PostgreSQL 資料庫設定 ---
# 你的 PostgreSQL 資料庫連線 URL
# 格式: jdbc:postgresql://<主機名稱或IP>:<埠號>/<資料庫名稱>
# localhost:5432 是 PostgreSQL 的預設主機和埠號
spring.datasource.url=jdbc:postgresql://localhost:5432/mydatabase
# 你的 PostgreSQL 登入帳號和密碼,請務必換成你自己的設定
spring.datasource.username=myuser
spring.datasource.password=mypassword
# 告訴 Hibernate 我們正在使用 PostgreSQL 的 SQL 方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
# 這是 JPA 中一個非常重要的設定,它決定了 Hibernate 如何處理資料表的結構
# 'update' 在開發初期很方便,但生產環境建議使用 'validate' 或 'none'
spring.jpa.hibernate.ddl-auto=update
現在重啟你的應用程式。如果設定無誤,它就會成功連線到你的 PostgreSQL 資料庫。如果你的應用程式中有定義 Entity,且 ddl-auto
設定為 update
或 create
,你將會在 PostgreSQL 資料庫中看到自動建立的資料表。
在 application.properties
中,有幾個關鍵設定值得我們深入了解,它們對應用程式的行為有著重大的影響。
spring.datasource.url
jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC
jdbc:postgresql://localhost:5432/mydatabase
jdbc:sqlserver://localhost:1433;databaseName=mydatabase
spring.datasource.username
/ spring.datasource.password
spring.jpa.hibernate.ddl-auto
值 | 說明 | 適用場景 | 風險 |
---|---|---|---|
none |
什麼都不做。完全關閉 DDL (Data Definition Language) 自動生成功能。 | 生產環境 (Production) | 最安全,無風險。資料庫結構需由 DBA 或遷移工具管理。 |
validate |
驗證。應用程式啟動時,Hibernate 會檢查你的 Java Entity 和資料庫的資料表結構是否一致,如果不一致就會拋出異常,阻止應用程式啟動。 | 生產環境、測試環境 | 安全。能及早發現模型與資料庫不一致的問題。 |
update |
更新。啟動時,Hibernate 會比較 Entity 和資料表,如果資料表不存在或缺少欄位,它會自動新增。 | 開發環境 (Development) | 中等。它不會處理欄位改名或刪除,可能導致資料庫結構髒亂。 |
create |
建立。每次應用程式啟動時,都會刪除所有舊的資料表,然後重新建立。 | 快速原型開發、自動化測試 | 極高!所有資料都會遺失! 絕對不能在正式環境使用。 |
create-drop |
建立並刪除。應用程式啟動時建立資料表,正常關閉時刪除資料表。 | 整合測試、特定情境的 Demo | 極高! 與 create 風險相同。 |
spring.jpa.show-sql
true
後,每次 JPA 執行資料庫操作時,都會在主控台(Console)印出它實際執行的 SQL 語法。spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
關於資料庫相關安裝教學,你可以參考及挑選以下其中一套資料庫教學影片,依影片內容練習來自行安裝:
Maven 依賴 (Dependency)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.0.0</version> <!-- 建議使用最新版本 -->
<scope>runtime</scope>
</dependency>
📌 MySQL Connector/J 在新版 Maven Central 裡 artifactId 改成
mysql-connector-j
,舊的mysql-connector-java
仍可用但已被取代。
application.properties
# --- MySQL 資料庫設定 ---
# MySQL 的連線 URL 格式:
# jdbc:mysql://<主機名稱或IP>:<埠號>/<資料庫名稱>
# localhost:3306 是 MySQL 的預設主機和埠號
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC
# MySQL 的登入帳號與密碼
spring.datasource.username=myuser
spring.datasource.password=mypassword
# Hibernate 方言 (Dialect),讓 JPA 知道要產生 MySQL 語法
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
Maven 依賴 (Dependency)
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.8.1.jre11</version> <!-- 選擇對應 JDK 版本的驅動 -->
<scope>runtime</scope>
</dependency>
📌 請根據你使用的 Java 版本選擇對應的
jre8
、jre11
、jre17
版本。
application.properties
# --- SQL Server 資料庫設定 ---
# SQL Server 的連線 URL 格式:
# jdbc:sqlserver://<主機名稱或IP>:<埠號>;databaseName=<資料庫名稱>
# localhost:1433 是 SQL Server 的預設主機和埠號
spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=mydatabase
# SQL Server 的登入帳號與密碼
spring.datasource.username=myuser
spring.datasource.password=mypassword
# Hibernate 方言 (Dialect),讓 JPA 知道要產生 SQL Server 語法
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
資料庫 | 預設埠號 | 驅動程式依賴 | URL 格式範例 | Hibernate Dialect |
---|---|---|---|---|
PostgreSQL | 5432 | org.postgresql:postgresql |
jdbc:postgresql://localhost:5432/mydatabase |
PostgreSQLDialect |
MySQL | 3306 | mysql:mysql-connector-j |
jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC |
MySQL8Dialect |
SQL Server | 1433 | com.microsoft.sqlserver:mssql-jdbc |
jdbc:sqlserver://localhost:1433;databaseName=mydatabase |
SQLServerDialect |