풀스택 백엔드 2026.05.22

syyu21b·2026년 5월 22일

풀스택 - 백엔드

목록 보기
21/46
post-thumbnail

[SECTION19. MyBatis + H2로 학생 관리 프로그램 생성]

● 프로젝트 준비

Gradle 의존성

implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
runtimeOnly 'com.h2database:h2'

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-webmvc'

Thymeleaf는 아직 안 붙여도 됨. 콘솔 앱으로 먼저 완성.


application.yml

spring:
  datasource:
    url: jdbc:h2:mem:testdb;MODE=MySQL
    driver-class-name: org.h2.Driver
    username: sa
    password:

  h2:
    console:
      enabled: true
      path: /h2-console

mybatis:
  mapper-locations: classpath:/mapper/**/*.xml
  configuration:
    map-underscore-to-camel-case: true
  • MODE=MySQL : 문법 호환 조금 더 편해짐(수업 안정성↑)
  • map-underscore-to-camel-case : created_atcreatedAt 자동 매핑

● 테이블/초기 데이터 준비(SQL 파일로 자동 실행)

src/main/resources/schema.sql

CREATE TABLE student (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    age INT NOT NULL,
    score INT NOT NULL
);

src/main/resources/data.sql (선택)

INSERT INTO student (name, age, score) VALUES ('홍길동', 20, 80);
INSERT INTO student (name, age, score) VALUES ('이순신', 25, 95);

실행 후 H2 콘솔에서 확인

http://localhost:8080/h2-console

JDBC URL: jdbc:h2:mem:testdb


● 도메인 클래스 만들기

Student.java

public class Student {
    private Long id;
    private String name;
    private int age;
    private int score;

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    public int getScore() { return score; }
    public void setScore(int score) { this.score = score; }
}

● MyBatis Mapper 작성 (⭐ 자바와 SQL 연결)

StudentMapper.java(Mapper 인터페이스)

import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Optional;

@Mapper
public interface StudentMapper {
    int insert(Student student);
    List<Student> findAll();
    Optional<Student> findById(Long id);
    int update(Student student);
    int deleteById(Long id);
}

src/main/resources/mapper/StudentMapper.xml (SQL을 담는 XML)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="StudentMapper">

    <insert id="insert" parameterType="com.example.mybatisexam.model.Student" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO student (name, age, score)
        VALUES (#{name}, #{age}, #{score})
    </insert>

    <select id="findAll" resultType="com.example.mybatisexam.model.Student">
        SELECT id, name, age, score
        FROM student
        ORDER BY id DESC
    </select>

    <select id="findById" parameterType="long" resultType="com.example.mybatisexam.model.Student">
        SELECT id, name, age, score
        FROM student
        WHERE id = #{id}
    </select>

    <update id="update" parameterType="com.example.mybatisexam.model.Student">
        UPDATE student
        SET name = #{name},
        age = #{age},
        score = #{score}
        WHERE id = #{id}
    </update>

    <delete id="deleteById" parameterType="long">
        DELETE FROM student
        WHERE id = #{id}
    </delete>

</mapper>

● 서비스 계층 만들기(로직 담당)

StudentService.java

import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class StudentService {

    private final StudentMapper studentMapper;

    public StudentService(StudentMapper studentMapper) {
        this.studentMapper = studentMapper;
    }

    public Long register(String name, int age, int score) {
        Student s = new Student();
        s.setName(name);
        s.setAge(age);
        s.setScore(score);

        studentMapper.insert(s);
        return s.getId();
    }

    public List<Student> list() {
        return studentMapper.findAll();
    }

    public Student find(Long id) {
        return studentMapper.findById(id).orElse(null);
    }

    public boolean update(Long id, String name, int age, int score) {
        Student s = new Student();
        s.setId(id);
        s.setName(name);
        s.setAge(age);
        s.setScore(score);
        return studentMapper.update(s) == 1;
    }

    public boolean delete(Long id) {
        return studentMapper.deleteById(id) == 1;
    }
}

● 콘솔 UI(지난 학생 관리 프로그램을 DB 버전으로)

MainApp.java (Spring Boot 실행 클래스)

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.List;
import java.util.Scanner;

@SpringBootApplication
public class MainApp implements CommandLineRunner {

    private final StudentService studentService;

    public MainApp(StudentService studentService) {
        this.studentService = studentService;
    }

    public static void main(String[] args) {
        SpringApplication.run(MainApp.class, args);
    }

    @Override
    public void run(String... args) {
        Scanner scn = new Scanner(System.in);
        System.out.println("학생 관리 프로그램(DB 버전)을 시작합니다.");

        while (true) {
            System.out.println("\n===== 명령어 목록 =====");
            System.out.println("1. 학생 등록");
            System.out.println("2. 학생 목록");
            System.out.println("3. 학생 검색");
            System.out.println("4. 학생 수정");
            System.out.println("5. 학생 삭제");
            System.out.println("0. 종료");
            System.out.print("명령어 번호: ");

            int cmd = scn.nextInt();
            scn.nextLine();

            switch (cmd) {
                case 0 -> {
                    System.out.println("프로그램 종료");
                    return;
                }
                case 1 -> {
                    System.out.print("학생 이름: ");
                    String name = scn.nextLine();
                    System.out.print("학생 나이: ");
                    int age = scn.nextInt();
                    System.out.print("학생 점수: ");
                    int score = scn.nextInt();
                    scn.nextLine();

                    Long id = studentService.register(name, age, score);
                    System.out.println("등록 완료! (id=" + id + ")");
                }
                case 2 -> {
                    List<Student> list = studentService.list();
                    if (list.isEmpty()) {
                        System.out.println("등록된 학생이 없습니다.");
                        break;
                    }
                    for (Student s : list) {
                        System.out.println("id: " + s.getId()
                                + " / 이름: " + s.getName()
                                + " / 나이: " + s.getAge()
                                + " / 점수: " + s.getScore());
                    }
                }
                case 3 -> {
                    System.out.print("검색할 학생 id: ");
                    long id = scn.nextLong();
                    scn.nextLine();

                    Student s = studentService.find(id);
                    if (s == null) {
                        System.out.println("해당 id의 학생이 없습니다.");
                    } else {
                        System.out.println("id: " + s.getId()
                                + " / 이름: " + s.getName()
                                + " / 나이: " + s.getAge()
                                + " / 점수: " + s.getScore());
                    }
                }
                case 4 -> {
                    System.out.print("수정할 학생 id: ");
                    long id = scn.nextLong();
                    scn.nextLine();

                    Student origin = studentService.find(id);
                    if (origin == null) {
                        System.out.println("해당 id의 학생이 없습니다.");
                        break;
                    }

                    System.out.println("현재 정보) 이름=" + origin.getName()
                            + ", 나이=" + origin.getAge()
                            + ", 점수=" + origin.getScore());

                    System.out.print("새 이름: ");
                    String name = scn.nextLine();
                    System.out.print("새 나이: ");
                    int age = scn.nextInt();
                    System.out.print("새 점수: ");
                    int score = scn.nextInt();
                    scn.nextLine();

                    boolean ok = studentService.update(id, name, age, score);
                    System.out.println(ok ? "수정 완료!" : "수정 실패!");
                }
                case 5 -> {
                    System.out.print("삭제할 학생 id: ");
                    long id = scn.nextLong();
                    scn.nextLine();

                    boolean ok = studentService.delete(id);
                    System.out.println(ok ? "삭제 완료!" : "삭제 실패!");
                }
                default -> System.out.println("잘못된 명령어입니다.");
            }
        }
    }
}

0개의 댓글