S SmartDocs
Serie: Springboot java 147 righe · Aggiornato 2026-08-14

User.java

Springboot/bookstore-api/src/main/java/com/example/bookstore/entity/User.java

package com.example.bookstore.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;

import java.time.LocalDateTime;

/**
 * 使用者 Entity(實體類別)——對應資料庫中的 users 資料表。
 *
 * 【JPA / Hibernate 核心觀念:ORM 物件關聯對映】
 * Entity 是「Java 物件」與「資料庫資料列」之間的橋樑。
 * Hibernate 會根據這個類別上的註解:
 *   1. 自動建立 / 更新資料表結構(依 application.yml 的 ddl-auto 設定)
 *   2. 查詢時,把結果集的每一列轉成一個 User 物件
 *   3. 儲存時,把 User 物件的內容轉成 INSERT / UPDATE 語句
 */
@Entity                      // 宣告這是一個 JPA Entity,交由 Hibernate 管理
@Table(
        name = "users",      // 指定資料表名稱。若不指定則預設用類別名稱 user,
                             // 但 user 是 MySQL 的保留字,容易出錯,因此改名為 users
        uniqueConstraints = {
                // 資料庫層級的「唯一性約束」:確保帳號與 Email 不重複
                @UniqueConstraint(name = "uk_users_username", columnNames = "username"),
                @UniqueConstraint(name = "uk_users_email",    columnNames = "email")
        }
)
public class User {

    /** 主鍵(Primary Key) */
    @Id
    // IDENTITY 策略:主鍵交給 MySQL 的 AUTO_INCREMENT 自動產生流水號
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /** 登入帳號:NOT NULL、最長 50 字元 */
    @Column(nullable = false, length = 50)
    private String username;

    /**
     * 密碼:儲存的是 BCrypt「雜湊值」,絕對不能存明碼!
     * BCrypt 雜湊字串長度約 60 字元,欄位保留 100 字元較保險。
     */
    @Column(nullable = false, length = 100)
    private String password;

    /** 電子信箱 */
    @Column(nullable = false, length = 100)
    private String email;

    /**
     * 角色:使用列舉(enum)型別。
     *
     * EnumType.STRING → 資料庫實際儲存 "ROLE_USER" 這樣的「文字」。
     * 若用預設的 EnumType.ORDINAL 會儲存 0、1 這種「順序數字」,
     * 一旦日後調整 enum 的宣告順序,舊資料的意義就全部錯亂,
     * 因此實務上幾乎一律使用 STRING。
     */
    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 20)
    private Role role;

    /**
     * 建立時間。
     * updatable = false → 之後執行 UPDATE 時,Hibernate 不會更動這個欄位。
     */
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    /**
     * 【JPA 規定】Entity 一定要有「無參數建構子」。
     * Hibernate 從資料庫讀取資料時,會先用它建立空物件,再逐一填入欄位值。
     */
    public User() {
    }

    /** 方便在程式中建立新使用者的建構子 */
    public User(String username, String password, String email, Role role) {
        this.username = username;
        this.password = password;
        this.email = email;
        this.role = role;
    }

    /**
     * 【生命週期回呼 Lifecycle Callback】
     * @PrePersist:在 Hibernate 執行 INSERT「之前」自動被呼叫,
     * 這裡用來自動填入建立時間,不需要每次手動設定。
     */
    @PrePersist
    protected void onCreate() {
        this.createdAt = LocalDateTime.now();
    }

    // ========================= Getter / Setter =========================
    // Hibernate 與 Jackson(JSON 轉換)都是透過 getter/setter 存取欄位。
    // 實務上許多團隊會用 Lombok 的 @Getter / @Setter 省去這些樣板程式碼;
    // 教學專案為了完整呈現原貌,選擇手動撰寫。

    public Long getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
}

Articoli correlati

Springboot java EN Aggiornato 2026-08-14

BookstoreApiApplication.java

BookstoreApiApplication.java — java source code from the Springboot learning materials (Springboot/bookstore-api/src/main/java/com/example/bookstore/BookstoreApiApplication.java).

Leggi l'articolo →
Springboot java EN Aggiornato 2026-08-14

DataInitializer.java

DataInitializer.java — java source code from the Springboot learning materials (Springboot/bookstore-api/src/main/java/com/example/bookstore/config/DataInitializer.java).

Leggi l'articolo →
Springboot java EN Aggiornato 2026-08-14

SecurityConfig.java

SecurityConfig.java — java source code from the Springboot learning materials (Springboot/bookstore-api/src/main/java/com/example/bookstore/config/SecurityConfig.java).

Leggi l'articolo →
Springboot java EN Aggiornato 2026-08-14

AuthController.java

AuthController.java — java source code from the Springboot learning materials (Springboot/bookstore-api/src/main/java/com/example/bookstore/controller/AuthController.java).

Leggi l'articolo →
Springboot java EN Aggiornato 2026-08-14

BookController.java

BookController.java — java source code from the Springboot learning materials (Springboot/bookstore-api/src/main/java/com/example/bookstore/controller/BookController.java).

Leggi l'articolo →
Springboot java EN Aggiornato 2026-08-14

ApiErrorResponse.java

ApiErrorResponse.java — java source code from the Springboot learning materials (Springboot/bookstore-api/src/main/java/com/example/bookstore/dto/ApiErrorResponse.java).

Leggi l'articolo →