[SECTION19. MyBatis + H2로 학생 관리 프로그램 생성]
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는 아직 안 붙여도 됨. 콘솔 앱으로 먼저 완성.
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_at → createdAt 자동 매핑src/main/resources/schema.sqlCREATE 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-consoleJDBC URL:
jdbc:h2:mem:testdb
Student.javapublic 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; }
}
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.javaimport 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;
}
}
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("잘못된 명령어입니다.");
}
}
}
}