S SmartDocs
Series: Springboot java 91 lines · Updated 2026-08-14

DataInitializer.java

Springboot/bookstore-api/src/main/java/com/example/bookstore/config/DataInitializer.java

package com.example.bookstore.config;

import com.example.bookstore.entity.Book;
import com.example.bookstore.entity.Role;
import com.example.bookstore.entity.User;
import com.example.bookstore.repository.BookRepository;
import com.example.bookstore.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

/**
 * 初始資料建立器——「教學專用」的種子資料(Seed Data)。
 *
 * 實作 CommandLineRunner 介面的 Bean,
 * 會在 Spring Boot「啟動完成後」自動執行一次 run() 方法。
 *
 * 這裡預先建立:
 *   1. 兩個測試帳號(admin 管理員、user 一般使用者)
 *   2. 三本範例書籍
 * 讓大家一啟動就能直接用 Postman 測試,不必先手動建資料。
 *
 * 注意:正式環境不會這樣做!正式專案通常使用
 * Flyway / Liquibase 這類「資料庫版本控管工具」管理初始資料。
 */
@Component
public class DataInitializer implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(DataInitializer.class);

    private final UserRepository userRepository;
    private final BookRepository bookRepository;
    private final PasswordEncoder passwordEncoder;

    public DataInitializer(UserRepository userRepository,
                           BookRepository bookRepository,
                           PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.bookRepository = bookRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public void run(String... args) {

        // ---------- 建立測試帳號(資料表是空的才建立,避免重複) ----------
        if (userRepository.count() == 0) {

            // 管理員:擁有全部權限(含 DELETE)
            userRepository.save(new User(
                    "admin",
                    passwordEncoder.encode("Admin@123"),   // 密碼一律加密後才儲存
                    "admin@example.com",
                    Role.ROLE_ADMIN));

            // 一般使用者:可查詢、新增、修改(不能刪除)
            userRepository.save(new User(
                    "user",
                    passwordEncoder.encode("User@123"),
                    "user@example.com",
                    Role.ROLE_USER));

            log.info("已建立測試帳號 -> admin / Admin@123(管理員)、user / User@123(一般使用者)");
        }

        // ---------- 建立範例書籍 ----------
        if (bookRepository.count() == 0) {

            bookRepository.save(new Book(
                    "Clean Code", "Robert C. Martin", "9780132350884",
                    new BigDecimal("1200.00"), 10,
                    "無瑕的程式碼:敏捷軟體開發技巧守則。"));

            bookRepository.save(new Book(
                    "Effective Java", "Joshua Bloch", "9780134685991",
                    new BigDecimal("1500.00"), 5,
                    "Java 程式設計的最佳實務指南,共 90 個條目。"));

            bookRepository.save(new Book(
                    "Spring 實戰", "Craig Walls", "9787115582866",
                    new BigDecimal("880.00"), 20,
                    "Spring in Action:涵蓋 Spring Boot 的實戰經典。"));

            log.info("已建立 {} 本範例書籍", bookRepository.count());
        }
    }
}

Related articles