본문 바로가기
Java/└ Mybatis

Mybatis) 학생 정보 등록 - DTO (별칭 등록, Mybatis 내장별칭)

by 박채니 2022. 8. 5.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


※ mybatis 설정파일 관련 아래 포스팅 참고

https://chanychu.tistory.com/354?category=991746 

 

Mybatis) Mybatis 사용법, 설정파일

안녕하세요, 코린이의 코딩 학습기 채니 입니다. 개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다. Mybatis - 데이터의 입력, 조회, 수정, 삭제 (CRUD)를 보다 편하게 하기 위해 xml

chanychu.tistory.com

 

sql

--=================================
-- mybatis
--=================================
create table student (
    no number,
    name varchar2(50) not null,
    tel char(11) not null,
    created_at date default sysdate,
    updated_at date,
    deleted_at date,    -- 학생정보 제거 시 실제 제거하는 것이 아닌 deleted_at을 sysdate로 작성
    constraint pk_student_no primary key(no)
);

create sequence seq_student_no;

select * from student;

insert into student(no, name, tel) values (seq_student_no.nextval, '홍길동', '01012341234');
insert into student(no, name, tel) values (seq_student_no.nextval, '신사임당', '01099998888');
insert into student(no, name, tel) values (seq_student_no.nextval, '세종대왕', '01022223333');

select * from student where deleted_at is null;

commit;

 

dto

Student

public class Student {
	private int no;
	private String name;
	private String tel;
	private LocalDateTime createdAt; // mybatis가 변환작업을 자동으로 잘해주기 때문에 java.sql.Date 대신 java.time.~ 이용!
	private LocalDateTime updatedAt;
	private LocalDateTime deletedAt;
	
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Student(int no, String name, String tel, LocalDateTime createdAt, LocalDateTime updatedAt,
			LocalDateTime deletedAt) {
		super();
		this.no = no;
		this.name = name;
		this.tel = tel;
		this.createdAt = createdAt;
		this.updatedAt = updatedAt;
		this.deletedAt = deletedAt;
	}

// getter, setter 생략

	@Override
	public String toString() {
		return "Student [no=" + no + ", name=" + name + ", tel=" + tel + ", createdAt=" + createdAt + ", updatedAt="
				+ updatedAt + ", deletedAt=" + deletedAt + "]";
	}	
}

 


학생 정보 등록 - DTO

 

EncodingFilter

package com.ce.app.common.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

/**
 * Servlet Filter implementation class EncodingFilter
 */
@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name="encodingType", value="utf-8")})
public class EncodingFilter implements Filter {
	private String encodingType;
	
    /**
     * Default constructor. 
     */
    public EncodingFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		request.setCharacterEncoding(encodingType);
		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		this.encodingType = fConfig.getInitParameter("encodingType");
	}
}

 

LogFilter

@WebFilter("/*")
public class LogFilter implements Filter {

    /**
     * Default constructor. 
     */
    public LogFilter() {
//        System.out.println("[LogFilter 생성]");
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
//		System.out.println("[LogFilter destroy]");
	}

	/**
	 * 필터를 통해 처리할 코드 작성
	 * - 전처리
	 * - 후처리
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// 전처리
		HttpServletRequest httpReq = (HttpServletRequest) request;
		String uri = httpReq.getRequestURI();	// /mvc/member/enroll - getRequestURL은 HttpServletRequest에 있으므로 다운캐스팅!
		String method = httpReq.getMethod();
		
		System.out.println("==========================================");
		System.out.printf("%s %s\n", method, uri);
		System.out.println("------------------------------------------");
		
		// filter chain의 다음 filter를 호출(마지막 filter라면 servlet 호출)
		chain.doFilter(request, response);
		
		// 후처리
		HttpServletResponse httpRes = (HttpServletResponse) response;
		System.out.println("__________________________________________");
		System.out.println(httpRes.getStatus());
		System.out.println();
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
//		System.out.println("[LogFilter init]");
	}
}

 

Controller

StudentEnrollController

public class StudentEnrollController extends AbstractController {
	static final Logger log = Logger.getLogger(StudentEnrollController.class);
	private StudentService studentService;
	
	public StudentEnrollController (StudentService studentService) {
		this.studentService = studentService;
	}
	
	@Override
	public String doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		return "student/studentEnroll";
	}
	
	@Override
	public String doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String name = request.getParameter("name");
		String tel = request.getParameter("tel");
		
		Student student = new Student();
		student.setName(name);
		student.setTel(tel);
		log.debug("student = " + student);
		
		int result = studentService.insertStudent(student);
		
		request.getSession().setAttribute("msg", "학생을 성공적으로 등록하였습니다.");
		
		return "redirect:/student/studentEnroll.do";
	}
}

@콘솔출력값
2022-08-05 11:48:17 DEBUG StudentEnrollController:37 - student = Student [no=0, name=유재석, tel=01011112222, createdAt=null, updatedAt=null, deletedAt=null]

 

Service

 

StudentService(interface)

public interface StudentService {

	int insertStudent(Student student);
	
}

 

StudentServiceImpl

public class StudentServiceImpl implements StudentService {
	private StudentDao studentDao;
	
	public StudentServiceImpl(StudentDao studentDao) {
		this.studentDao = studentDao;
	}
	
	@Override
	public int insertStudent(Student student) {
		SqlSession sqlSession = getSqlSession();
		int result = 0;
		try {
			result = studentDao.insertStudent(sqlSession, student);
			sqlSession.commit();
		} catch (Exception e) {
			sqlSession.rollback();
			throw e;
		} finally {
			sqlSession.close();
		}
		return result;
	}
}

 

Dao

StudentDao(interface)

public interface StudentDao {

	int insertStudent(SqlSession sqlSession, Student student);
	
}

 

StudentDaoImpl

public class StudentDaoImpl implements StudentDao {
	@Override
	public int insertStudent(SqlSession sqlSession, Student student) {
		return sqlSession.insert("student.insertStudent", student);
	}
}

sqlSession의 insert 메소드를 이용하여 insert처리를 해줍니다.

"student"xml-mapper의 namespace를 의미

"insertStudent"태그의 id값을 의미

 

student-mapping.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="student"> 
	<insert id="insertStudent" parameterType="com.ce.app.student.model.dto.Student">
		insert into student(no, name, tel) values(seq_student_no.nextval, #{name}, #{tel}) <!-- name, tel은 getName/getTel의 name/tel -> OGNL -->
	</insert>
</mapper>

#{name}, #{tel}은 Student class의 필드가 아닌 getter에서 get제외하고 소문자로 시작하는 메소드명을 가져와 참조합니다. ( OGNL (Object Graph Navigation Language))

 

또한 mapper에서는 모든 클래스/타입을 패키지명 포함 풀네임으로 작성해야합니다.

현재 Student 객체를 전달 받기 때문에 parameterType은 Student 클래스의 풀네임으로 주었습니다. (추후 별칭으로 간략하게 사용 가능)

(parameterType은 생략 가능!!)

 

studentEnroll.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Mybatis 실습</title>
<style>
div.enroll-container {text-align:center;}
table {margin:0 auto;border:1px solid; border-collapse:collapse;}
th,td {border:1px solid; padding:5px;}
th {text-align:right;}
td {text-align:left;}
td:last-of-type {text-align:center;}
</style>

<c:if test="${not empty msg}">
	<script>
		alert("${msg}");
	</script>
	<c:remove var="msg" scope="session"/>
</c:if>

</head>
<body>
	<div class="enroll-container">
		<h2>학생등록(DTO)</h2>
		<form method="POST">
			<table>
				<tr>
					<th>학생이름</th>
					<td>
						<input type="text" name="name" required/>
					</td>
				</tr>
				<tr>
					<th>전화번호</th>
					<td>
						<input type="tel" name="tel" maxlength="11" required/>
					</td>
				</tr>
				<tr>
					<td colspan="2">
						<input type="submit" value="등록" />
					</td>
				</tr>
			</table>
		</form>
	</div>
</body>
</html>

등록이 성공적으로 이루어진 것을 확인할 수 있습니다.


클래스 별칭 등록

 

mybatis-config.xml

<typeAliases>

  <typeAliases>
  	<typeAlias type="com.ce.app.student.model.dto.Student" alias="student"/>
  </typeAliases>

com.ce.app.student.model.dto 하위의 Student 클래스의 별칭을 'student'로 사용하겠다는 의미입니다.

이 외 패키지로 묶어서도 관리 가능합니다.

 

  <typeAliases>
  	<package name="com.ce.app"/> <!-- com.ce.app 하위에 모든 클래스를 소문자로 시작하는 별칭으로 등록 => 클래스 이름 중복 유의 -->
  </typeAliases>

com.ce.app 하위에 위치한 모든 클래스들을 소문자로 시작하는 별칭으로 등록하여 사용하겠다는 의미입니다.

다만, 다른 패키지의 동일한 클래스명이 있는 경우 오류가 발생되므로 유의!!

 

<mapper namespace="student"> 
	<insert id="insertStudent" parameterType="student">
		insert into student(no, name, tel) values(seq_student_no.nextval, #{name}, #{tel}) <!-- name, tel은 getName/getTel의 name/tel -> OGNL -->
	</insert>
</mapper>

별칭 등록을 해놓으면, parameterType이나 resultType에서 풀네임이 아닌 별칭으로 참조 가능합니다.

 

※ Mybatis 내장 별칭