본 글은 이전 글들과 이어진다.
2019/08/01 - [Spring] - Spring boot에서 maven을 통해 mybatis MySQL 사용하기 - select
2019/08/07 - [Spring] - Spring boot에서 maven을 통해 mybatis MySQL 사용하기 - insert
저번 글에서 문제 삼았던 부분이 롤 프로게임팀은 t1 뿐만 아니라 여러 팀이 있는데 나는 t1 하나만 보고 프로젝트를 작성했다. 그래서 xml에는 select * from t1, insert into t1 ~~~ 처럼 오로지 t1 테이블에만 접근이 가능한 쿼리문을 작성했다. 여기서 나는 GenG, Griffin 등 다양한 팀의 명단을 출력 및 선수 추가를 하고 싶다.
우선 GenG를 더 추가해주었다.
1. 데이터베이스에 GenG 테이블 추가
사용되는 쿼리문은 t1 테이블을 생성할 때와 같다.
CREATE TABLE lol.geng (id INT NOT NULL,
name VARCHAR(100) NOT NULL,
nickname VARCHAR(128) NOT NULL,
position VARCHAR(100) NOT NULL, PRIMARY KEY(id));
2. 명단을 출력할 팀을 선택하는 페이지 생성
나는 selectTeam.jsp라는 페이지를 만들었다.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>롤 프로게이머 팀</title>
</head>
<body>
<form name="selectTeam" action="/list" method="post" id="select">
<select name="team" id="team">
<option value="t1"> T1 </option>
<option value="geng"> GenG </option>
</select>
<input type="submit" name="selectBut" id="selectBut" value="팀 선택" />
</form>
</body>
</html>
select box에서 팀을 선택하면 list 페이지에서 해당 팀의 명단을 출력해준다. 그러면 우리는 쿼리문에서 select * from t1; 이 아닌 여기서 선택한 팀이 select 되도록 수정해줘야 한다.
3. xml 수정
<select id="getMember" resultType="com.chojpsh1.lol_pro.model.MemberModel">
select * from ${team}
</select>
xml에서 getMember 의 쿼리문을 수정해준다. 여기서 이전에 insert를 할때 사용자가 입력한 id, name, nickname, position 값들은 #{ }으로 쿼리문에 넣어주는데 테이블 명인 team은 ${ }으로 설정해준다. ${과 #{의 차이점은 무엇일까?
결론은 #{은 Prepared Statement이고 ${은 그냥 준비되지 않고 직접 해당 값으로 대체된다. 그래서 #{은 안전하지만 ${은 안전하지 않다. 하지만 meta data(데이터 열, 행의 이름 또는 테이블 명)를 변경할 때에는 쿼리문이 수정되어야 한다. 그래서 해당 부분의 데이터를 변경하고 싶을 땐 ${을 사용해서 바꿔주는 데 ${는 원래 사용자 입력이 허용되지 않도록 하는 게 좋다.
- Prepared Statement와 Statement 차이점
Statement는 실제 데이터베이스에 쿼리를 보내기 위해 필요한 객체이다. 이 객체는 Connect 객체의 연결 정보를 가져와서 DB에 접근하므로 이 객체를 사용하기 위해서는 Connection 객체가 먼저 존재해야 한다.
Prepared Statement는 쿼리 수행마다 쿼리 문장 분석하고 컴파일 후 실행하는 statement와 달리 처음에만 해당 작업을 수행하고 캐시에 담아 재사용한다. 예를 들어, 삽입 쿼리문에 삽입되는 값이 변경되는 부분에 ? 로 작성하고 PreparedStatement 객체를 생성 후 해당 값이 int라면 setInt(?표 인덱스, 값) 함수를 통해 쿼리문을 재사용할 수 있다. 하지만 이렇다보니 한번에 쿼리문을 파악하기 힘들 수도 있다.
그렇담 getMember에서 ${team}에 해당하는 데이터를 parameter로 받을 수 있게끔 수정해줘야 한다.
4. MemberDao 인터페이스에서 getMember 함수 수정
package com.chojpsh1.lol_pro.dao;
import com.chojpsh1.lol_pro.model.MemberModel;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface MemberDao {
List<MemberModel> getMember(@Param("team") String team);
void setMember(MemberModel member);
}
위와 같이 getMember 함수의 parameter 부분에 @Param annotation으로 team을 받는다. 그럼 getMember를 호출하는 Service에도 코드를 조금 수정해줘야 한다.
5. MemberService, MemberServiceImpl 수정
먼저 인터페이스 (MemberService)부터 수정한다.
package com.chojpsh1.lol_pro.service;
import com.chojpsh1.lol_pro.model.MemberModel;
import java.util.List;
public interface MemberService {
List<MemberModel> printMember(String team);
void insertMember(MemberModel member);
}
getMember 함수에게 전달해줄 team 데이터를 printMember 함수의 인자로 받는다.
package com.chojpsh1.lol_pro.service.Impl;
import com.chojpsh1.lol_pro.dao.MemberDao;
import com.chojpsh1.lol_pro.model.MemberModel;
import com.chojpsh1.lol_pro.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class MemberServiceImpl implements MemberService {
@Autowired
private MemberDao dao;
@Override
public List<MemberModel> printMember(String team) {
List<MemberModel> member = dao.getMember(team);
return member;
}
@Override
public void insertMember(MemberModel member) {
dao.setMember(member);
}
}
MemberServiceImpl 클래스에서는 인자로 받은 team을 그대로 getMember 함수 인자로 전달만 해주도록 수정하면 끝이다.
6. Controller 수정
Controller에서는 selectTeam.jsp 페이지를 띄우기 위해 selectTeam이 url에 요청되면 selectTeam String을 반환하는 selectTeam() 함수를 추가구현할 것이다. 그리고 list 요청 시 실행되는 list()함수를 수정해야 한다. 이전에는 페이지로부터 어떠한 데이터를 받는거 없이 그냥 쿼리문을 실행시켜 t1의 선수명단을 출력시켰는데 이제는 selectTeam.jsp 페이지에서 사용자가 선택한 팀 명단을 출력해야하므로 무슨 팀을 선택했는지 받아야한다. 받은 데이터를 printMember 함수 인자로 전달하도록 수정해주면 된다.
@RequestMapping("/selectTeam")
public String selectTeam(Model model) { return "selectTeam"; }
@RequestMapping("/list")
public String list(Model model, HttpServletRequest request) {
String team = (String)request.getParameter("team");
List<MemberModel> member = memberService.printMember(team);
model.addAttribute("memberList", member);
return "list";
}
위 두 함수가 MemberController에서 추가 구현된 부분이다.
여기까지 하고 프로젝트 실행시켜 localhost:8080/selectTeam으로 이동하면 다음과 같이 선택창이 뜬다.
여기서 '팀 선택'을 누르면 list 페이지로 이동하면서 명단이 출력된다.
원하는 테이블을 선택해서 select 하는 것은 되었다. 그럼 이제 원하는 테이블에 insert 하는 것을 해보자.
7. MemberModel 수정
이건 나의 실수인 거 같은데 insert 할때에도 그냥 DAO클래스에서 인자에 @Param annotation을 이용해서 team 을 받으면 되었을 텐데, 이걸 알기 전에 insert 먼저 구현했다. (select를 나중에 구현하고) 그래서 insert 부분은 select와 다소 테이블 명을 넘겨주는 부분이 다르다. select를 구현하면서 @Param annotation을 이용하는 방법은 또 다른 방법이 있을까 싶어 구글링을 통해 알게된 내용이다. insert 부분은 일단 내가 생각하는 대로 작성해본 방법이다.
우선 MemberModel은 team 정보를 담고 있어야 한다. Controller 부분에서 Service의 함수를 호출해 DAO에서 쿼리문에 테이블 명을 넣을 때 MemberModel이 team 정보를 가지고 있어야 수훨하다고 생각했다.
package com.chojpsh1.lol_pro.model;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class MemberModel {
private int id;
private String name;
private String nickname;
private String position;
private String team;
}
위와 같이 team 변수를 하나 추가시켜주었다.
8. MemberController 수정
마찬가지로 insert 함수에서 team 값을 set해주는 코드를 추가하였다. 이때 list 페이지를 띄울 때 '?team=팀이름 부분이 추가되었다. list()함수에서 team 명을 파라미터로 받아 select 쿼리문에 적용시켜 출력하기 때문에 team 이름을 전달해줘야 한다.
@RequestMapping(value = "/insert", method = RequestMethod.POST)
public ModelAndView insert(HttpServletRequest request) throws UnsupportedEncodingException {
request.setCharacterEncoding("UTF-8");
MemberModel member = new MemberModel();
member.setId(Integer.parseInt(request.getParameter("id")));
member.setName((String)request.getParameter("name"));
member.setNickname((String)request.getParameter("nickname"));
member.setPosition((String)request.getParameter("position"));
member.setTeam((String)request.getParameter("team"));
memberService.insertMember(member);
ModelAndView result = new ModelAndView("redirect:/list?team="+member.getTeam());
return result;
}
9. xml 수정
xml에서 테이블 명 부분에 ${team}으로 하면 이 방법에서는 DAO 부분에 @Param annotation을 직접 인자로 주어 할 필요는 없다. 아래와 같이 쿼리문을 바꿔주면 된다.
<insert id="setMember" parameterType="com.chojpsh1.lol_pro.model.MemberModel">
INSERT INTO lol.${team} VALUES(#{id}, #{name}, #{nickname}, #{position})
</insert>
selectMember 페이지에서 아래와 같이 정보를 입력하고
'추가하기' 버튼을 누르면 list 페이지로 이동하면서 geng 테이블의 정보가 출력된다.
데이터베이스에서 확인해보아도 데이터가 잘 삽입되어 있다.
'Spring' 카테고리의 다른 글
Spring boot에서 maven을 통해 mybatis MySQL 사용하기 - insert (0) | 2019.08.07 |
---|---|
Spring boot에서 maven을 통해 mybatis MySQL 사용하기 - select (3) | 2019.08.01 |
[MacOS] intelliJ에서 tomcat server로 Spring (2) | 2019.03.29 |