1) SpringBoot
1-1) 학생 성적 관리 예제
1-1-1) 학생 성적 입력 / 목록 출력 / 수정 및 삭제
1) SpringBoot
1-1) 학생 성적 관리 예제
DB에 "student" Table 생성 - 작업환경(DBeaver)
-- DB 구조
-- 학생 성적 관리(테이블명 : student)
create table student(
-- 컬럼명 자료형 제약조건 설명
stid varchar(10) primary key, -- 학번(기본키)
stname varchar(30) not null, -- 학생이름
korean int default 0, -- 국어점수
english int default 0, -- 영어점수
math int default 0 -- 수학점수
);
select * from student;
insert into student(stid, stname, korean, english, math) values('asdf1234', '홍길동', 70, 80, 90);
insert into student(stid, stname, korean, english, math) values('fghj1234', '마동석', 50, 90, 80);
insert into student(stid, stname, korean, english, math) values('hjkp1234', '유재석', 70, 90, 60);
insert into student(stid, stname, korean, english, math) values('qwer1234', '강호동', 40, 60, 80);
delete from student where stname = '이광수';
drop table student;
commit;
1-1-1) 학생 성적 생성 / 목록 출력 / 수정 및 삭제
(1) [src/main/resources] - [templates] 안에 home.html 파일 생성 후 아래와 같이 작성
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>학생 성적 관리</title>
</head>
<body>
<h1>[ 학생 성적 관리 ]</h1>
<p><a href="gradeWrite">성적 입력하기</a></p>
<p><a href="gradeSelectAll">전체 조회하기</a></p>
</body>
</html>
(2) [src/main/java] - [net.datasa.test.controller] 안에 HomeController.java 파일 생성 후 아래와 같이 작성
package net.datasa.test.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping({"", "/"})
public String home() {
return "home";
}
}
(3) [src/main/java] - [net.datasa.test.controller] 안에 StudentController.java 파일 생성 후 아래와 같이 작성
package net.datasa.test.controller;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.datasa.test.domain.dto.StudentDTO;
import net.datasa.test.service.StudentService;
@Controller
@Slf4j
@RequiredArgsConstructor
public class StudentController {
// 명시적인 생성자를 통한 초기화(Service 관련)
// @Autowired보다 권장되며, 테스트가 용이함. 주입되지 않은 경우에는 컴파일 타임에 오류가 발생함.
private final StudentService studentService;
/**
* 성적 관련 점수 입력폼으로 이동
* @return 점수 입력 HTML 파일 경로
*/
@GetMapping("gradeWrite")
public String gradeWrite() {
return "gradeForm";
}
/**
* 점수 입력폼의 데이터를 받아서 Service로 전달하여 DB에 저장
* @param gradeDTO 사용자가 입력한 값(학번, 이름, 과목별 점수)이 저장된 객체
* @return 전체 학생 정보 조회 화면(목록 화면 - gradeSelectAll)에 해당하는 HTML 파일 경로
*/
@PostMapping("gradeWrite")
public String gradeWrite(@ModelAttribute StudentDTO studentDTO) {
log.debug("입력한 학생 정보 : {} ", studentDTO);
studentService.writeSave(studentDTO);
return "redirect:/";
}
/**
* 전체 학생 정보(학번, 이름, 과목별 점수, 총합) 조회
* @return 전체 학생 정보 조회 화면(목록 화면 - gradeSelectAll)에 해당하는 HTML 파일 경로
*/
@GetMapping("gradeSelectAll")
public String gradeSelectAll(Model model) {
List<StudentDTO> studentList = studentService.selectAll();
model.addAttribute("studentList", studentList);
return "gradeList";
}
/**
* 학번(stid)을 전달받아 학생 정보 삭제
* @param stid 삭제할 학번
* @return 전체 학생 정보 목록 보기 페이지로 이동
*/
@GetMapping("deleteStudent")
public String deleteStudent(@RequestParam("stid") String stid) {
studentService.delete(stid);
return "redirect:gradeSelectAll";
}
/**
* 수정 페이지로 이동
* @param stid 수정할 학번
* @param model HTML 파일로 값을 전달해주는 객체
* @return 학생 정보 수정폼의 HTML 파일 경로
*/
@GetMapping("gradeUpdate")
public String gradeUpdate(@RequestParam("stid") String stid, Model model) {
StudentDTO studentDTO = studentService.select(stid);
model.addAttribute("student", studentDTO);
return "updateForm";
}
/**
* 사용자가 폼에 입력(수정)한 학생 정보를 DB에 저장
* @param studentDTO 사용자가 수정한 학생 정보를 저장한 객체
* @return 전체 학생 정보 목록 보기 페이지로 이동
*/
@PostMapping("gradeUpdate")
public String gradeUpdate(@ModelAttribute StudentDTO studentDTO) {
log.debug("수정한 학생 정보 : {}", studentDTO);
studentService.update(studentDTO);
return "redirect:gradeSelectAll";
}
}
(4) [src/main/java] - [net.datasa.test.service] 안에 StudentService.java 파일 생성 후 아래와 같이 작성
package net.datasa.test.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import jakarta.persistence.EntityNotFoundException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import net.datasa.test.domain.dto.StudentDTO;
import net.datasa.test.domain.entity.StudentEntity;
import net.datasa.test.repository.StudentRepository;
/**
* 학생 정보를 관리하는 서비스 클래스
*/
@Service
@RequiredArgsConstructor
@Transactional
public class StudentService {
private final StudentRepository studentRepository;
/**
* 학생 정보를 전달 받아서 DB에 저장함
* @param studentDTO entity에 담아 DB에 저장할 학생 정보를 담은 객체
*/
public void writeSave(StudentDTO studentDTO) {
StudentEntity entity = new StudentEntity();
entity.setStid(studentDTO.getStid());
entity.setStname(studentDTO.getStname());
entity.setKorean(studentDTO.getKorean());
entity.setEnglish(studentDTO.getEnglish());
entity.setMath(studentDTO.getMath());
studentRepository.save(entity);
}
/**
* 모든 학생 정보 조회
* @return 모든 학생 정보를 담은 객체의 리스트
*/
public List<StudentDTO> selectAll() {
List<StudentEntity> entityList = studentRepository.findAll();
List<StudentDTO> dtoList = new ArrayList<>();
for (StudentEntity entity : entityList) {
StudentDTO dto = new StudentDTO();
dto.setStid(entity.getStid());
dto.setStname(entity.getStname());
dto.setKorean(entity.getKorean());
dto.setEnglish(entity.getEnglish());
dto.setMath(entity.getMath());
dtoList.add(dto);
}
return dtoList;
}
/**
* 학생 정보 삭제
* @param stid 삭제할 학생의 학번
*/
public void delete(String stid) {
StudentEntity studentEntity = studentRepository.findById(stid)
.orElseThrow(() -> new EntityNotFoundException("학생 정보가 없습니다."));
studentRepository.delete(studentEntity);
}
/**
* 학생 정보 조회
* @param stid 조회할 학생의 학번
* @return DB로부터의 조회 결과를 담은 객체
*/
public StudentDTO select(String stid) {
StudentEntity entity = studentRepository.findById(stid)
.orElseThrow(() -> new EntityNotFoundException("학생 정보가 없습니다."));
StudentDTO dto = new StudentDTO();
dto.setStid(entity.getStid());
dto.setStname(entity.getStname());
dto.setKorean(entity.getKorean());
dto.setEnglish(entity.getEnglish());
dto.setMath(entity.getMath());
return dto;
}
/**
* 학생 정보를 학번을 기준으로 수정
* @param studentDTO 수정할 학생 정보
*/
public void update(StudentDTO studentDTO) {
//DB의 정보를 조회
StudentEntity entity = studentRepository.findById(studentDTO.getStid())
.orElseThrow(() -> new EntityNotFoundException("학생 정보가 없습니다."));
// StudentDTO의 수정할 정보를 entity에 세팅
entity.setKorean(studentDTO.getKorean());
entity.setEnglish(studentDTO.getEnglish());
entity.setMath(studentDTO.getMath());
// entity 저장
studentRepository.save(entity);
}
}
(5) [src/main/java] - [net.datasa.test.domain.dto] 안에 StudentDTO.java 파일 생성 후 아래와 같이 작성
package net.datasa.test.domain.dto;
import lombok.Data;
/**
* 학생 정보 DTO
*/
@Data
public class StudentDTO {
private String stid; // 학번
private String stname; // 학생이름
private Integer korean; // 국어점수
private Integer english; // 영어점수
private Integer math; // 수학점수
}
(6) [src/main/java] - [net.datasa.test.repository] 안에 StudentRepository.java 파일 생성 후 아래와 같이 작성
package net.datasa.test.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import net.datasa.test.domain.entity.StudentEntity;
/**
* 학생 정보 관련 Repository
*/
@Repository
public interface StudentRepository extends JpaRepository<StudentEntity, String> {
}
(7) [src/main/java] - [net.datasa.test.domain.entity] 안에 StudentEntity.java 파일 생성 후 아래와 같이 작성
package net.datasa.test.domain.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
/**
* 학생 정보 엔티티
*/
@Data
@Entity
@Table(name = "student")
public class StudentEntity {
@Id
@Column(name = "stid", nullable = false, length = 10)
private String stid;
@Column(name = "stname", nullable = false, length = 30)
private String stname;
@Column(name = "korean", columnDefinition = "int default 0")
private Integer korean = 0;
@Column(name = "english", columnDefinition = "int default 0")
private Integer english = 0;
@Column(name = "math", columnDefinition = "int default 0")
private Integer math = 0;
}
(8) [src/main/resources] - [templates] 안에 gradeForm.html 파일 생성 후 아래와 같이 작성
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>성적 입력</title>
</head>
<body>
<h1>[ 성적 입력 ]</h1>
<form action="gradeWrite" method="post">
<table>
<tr>
<th>학번</th>
<td><input type="text" name="stid" required="required"></td>
</tr>
<tr>
<th>이름</th>
<td><input type="text" name="stname" required="required"></td>
</tr>
<tr>
<th>국어점수</th>
<td><input type="number" name="korean" value=0></td>
</tr>
<tr>
<th>영어점수</th>
<td><input type="number" name="english" value=0></td>
</tr>
<tr>
<th>수학점수</th>
<td><input type="number" name="math" value=0></td>
</tr>
<tr>
<td><input type="submit" value="저장"></td>
</tr>
</table>
</form>
</body>
</html>
(9) [src/main/resources] - [templates] 안에 gradeList.html 파일 생성 후 아래와 같이 작성
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>전체 학생 조회</title>
</head>
<body>
<h1>[ 전체 학생 조회 ]</h1>
<table>
<tr>
<th>번호</th>
<th>학번</th>
<th>이름</th>
<th>국어</th>
<th>영어</th>
<th>수학</th>
<th>총점</th>
<th></th>
<th></th>
</tr>
<tr th:if="${studentList == null or studentList.isEmpty()}">
<td colspan="9">조회 결과가 없습니다.</td>
</tr>
<tr th:if="${studentList}" th:each="student, status : ${studentList}">
<td th:text="${status.count}"></td>
<td th:text="${student.stid}"></td>
<td th:text="${student.stname}"></td>
<td th:text="${student.korean}"></td>
<td th:text="${student.english}"></td>
<td th:text="${student.math}"></td>
<!-- 국어, 영어, 수학점수의 총점 -->
<td th:text="${student.korean + student.english + student.math}"></td>
<td><a th:href="|deleteStudent?stid=${student.stid}|">삭제</a></td>
<td><a th:href="|gradeUpdate?stid=${student.stid}|">수정</a></td>
</tr>
</table>
</body>
</html>
(10) [src/main/resources] - [templates] 안에 updateForm.html 파일 생성 후 아래와 같이 작성
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>학생 점수 수정</title>
</head>
<body>
<h1>[ 학생 점수 수정 ]</h1>
<form action="gradeUpdate" method="post">
<table>
<tr>
<th>학번</th>
<td><input type="text" name="stid" th:value="${student.stid}" readonly></td>
</tr>
<tr>
<th>이름</th>
<td><input type="text" name="stname" th:value="${student.stname}" readonly></td>
</tr>
<tr>
<th>국어점수</th>
<td><input type="number" name="korean" th:value="${student.korean}"></td>
</tr>
<tr>
<th>영어점수</th>
<td><input type="number" name="english" th:value="${student.english}"></td>
</tr>
<tr>
<th>수학점수</th>
<td><input type="number" name="math" th:value="${student.math}"></td>
</tr>
<tr>
<td><input type="submit" value="저장"></td>
</tr>
</table>
</form>
</body>
</html>
(11) 결과 화면
첫 접속 화면
"성적 입력하기" 문구 클릭 시 학생 점수 입력폼 화면 : 목록 및 DB에 저장됨
"전체 조회하기" 문구 클릭 시 전체 학생 점수 목록 화면
"전체 학생 성적 목록" 화면에서 "삭제" 버튼 클릭 시 화면 : "정우성" 학생 삭제 예시
"전체 학생 성적 목록" 화면에서 "수정" 버튼 클릭 시 화면 : 학생 성적 수정폼으로 이동함