ㅁ 테이블의 각 행의 맨 앞에 셀을 추가해서 체크박스 요소를 둔다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>회원 검색 결과</h3>
<c:choose>
<c:when test="${ empty list }">
검색 결과가 없습니다.
</c:when>
<c:otherwise>
<form action="${ contextPath }/delete.me">
<table border="1">
<thead>
<tr>
<th></th>
<th>번호</th>
<th>아이디</th>
<th>이름</th>
<th>주소</th>
</tr>
</thead>
<tbody>
<c:forEach var="m" items="${ list }">
<tr>
<td><input type="checkbox" name="delNo" value="${ m.userNo }"></td>
<td>${ m.userNo }</td>
<td>${ m.userId }</td>
<td>${ m.userName }</td>
<td>${ m.address }</td>
</tr>
</c:forEach>
</tbody>
</table>
<button type="submit">탈퇴</button>
</form>
</c:otherwise>
</c:choose>
</body>
</html>
- 각 행은 list에서 m을 뽑아서 만들어져 있다. form으로 감싸서 요청시 checked된 각 행의 회원 번호를 넘긴다.
- 삭제 요청도 post로 한다. get방식은 주로 조회요청이다.
조회요청이 get방식, insert+update+delete는 post방식이라고 생각하면 된다.
- 그런데 조회여도 요청 데이터가 길거나, url에 데이터가 노출돼선 안되면 post로 한다.
ㅁ com.br.mybatis.member.controller에 MemberDeleteController 서블릿을만든다.
package com.br.mybatis.member.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.br.mybatis.member.service.MemberServiceImpl;
/**
* Servlet implementation class MemberDeleteController
*/
@WebServlet("/delete.me")
public class MemberDeleteController extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public MemberDeleteController() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String[] deleteNo = request.getParameterValues("delNo"); // ["1", "13", "20"]
int result = new MemberServiceImpl().deleteMember(deleteNo);
if(result == deleteNo.length) {
System.out.println("성공");
response.sendRedirect(request.getContextPath());
}else {
System.out.println("실패");
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
ㅁ MemberService
package com.br.mybatis.member.service;
import java.util.List;
import java.util.Map;
import com.br.mybatis.member.dto.MemberDto;
public interface MemberService {
// 인터페이스에서 public abstract를 붙이지 않아도 모든 메서드는 자동으로 추상 메서드로 취급됩니다.
// 회원정보 상세조회
MemberDto selectMember(int userNo);
// 회원정보 변경
int updateMember(MemberDto m);
// 회원 검색
List<MemberDto> selectSearchList(Map<String, Object> map);
// 회원 탈퇴
int deleteMember(String[] deleteNo);
}
ㅁ MemberServiceImpl
package com.br.mybatis.member.service;
import org.apache.ibatis.session.SqlSession;
import static com.br.mybatis.common.template.Template.*;
import java.util.List;
import java.util.Map;
import com.br.mybatis.member.dao.MemberDao;
import com.br.mybatis.member.dto.MemberDto;
public class MemberServiceImpl implements MemberService {
private MemberDao memberDao = new MemberDao();
@Override
public MemberDto selectMember(int userNo) {
SqlSession sqlSession = /*Template.*/getSqlSession();
MemberDto m = memberDao.selectMember(sqlSession, userNo);
sqlSession.close();
return m;
}
@Override
public int updateMember(MemberDto m) {
SqlSession sqlSession = getSqlSession();
int result = memberDao.updateMember(sqlSession, m);
if(result > 0) {
sqlSession.commit();
}
sqlSession.close();
return result;
}
@Override
public List<MemberDto> selectSearchList(Map<String, Object> map) {
SqlSession sqlSession = getSqlSession();
List<MemberDto> list = memberDao.selectSearchList(sqlSession, map);
sqlSession.close();
return list;
}
public int deleteMember(String[] deleteNo) {
SqlSession sqlSession = getSqlSession();
int result = memberDao.deleteMember(sqlSession, deleteNo);
if(result == deleteNo.length) {
sqlSession.commit();
}
sqlSession.close();
return result;
}
}
ㅁ MemberDao
package com.br.mybatis.member.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import com.br.mybatis.member.dto.MemberDto;
public class MemberDao {
public MemberDto selectMember(SqlSession sqlSession, int userNo) {
return sqlSession.selectOne("memberMapper.selectMember", userNo);
}
public int updateMember(SqlSession sqlSession, MemberDto m) {
return sqlSession.update("memberMapper.updateMember", m);
}
public List<MemberDto> selectSearchList(SqlSession sqlSession, Map<String, Object> map) {
return sqlSession.selectList("memberMapper.selectSearchList", map);
}
public int deleteMember(SqlSession sqlSession, String[] deleteNo) {
return sqlSession.update("memberMapper.deleteMember", deleteNo);
}
}
- 회원탈퇴지만 delete를 하지 않고 update로 status 컬럼값만 바꾼다.
ㅁ member-mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<mapper namespace="memberMapper">
<resultMap id="memberResultMap" type="MemberDto">
<result column="user_no" property="userNo" />
<result column="user_id" property="userId" />
<result column="user_name" property="userName" />
<result column="phone" property="phone" />
<result column="email" property="email" />
<result column="address" property="address" />
<result column="interest" property="interest" typeHandler="StringArrTypeHandler"/>
</resultMap>
<select id="selectMember" resultMap="memberResultMap">
select
user_no
, user_id
, user_name
, phone
, email
, address
, interest
from member
where status in ('U', 'A')
and user_no = #{ userNo }
</select>
<update id="updateMember">
update
member
set
user_name = #{userName}
, phone = #{phone}
, email = #{email}
, address = #{address}
, interest = #{interest, typeHandler=StringArrTypeHandler}
where user_no = #{userNo}
</update>
<select id="selectSearchList" resultMap="memberResultMap">
select
user_no
, user_id
, user_name
, address
from member
where status in ('U', 'A')
<choose>
<when test="condition == 'no'">
and user_no like '%' || #{keyword} || '%'
</when>
<when test='condition == "name"'>
and user_name like '%' || #{keyword} || '%'
</when>
<otherwise>
and user_id like '%${keyword}%'
</otherwise>
</choose>
</select>
<update id="deleteMember">
update
member
set status = 'R'
<where>
<foreach item="no" collection="array"
open="user_no in (" separator="," close=")">
#{no}
</foreach>
</where>
</update>
</mapper>
- memberMapper 파일의 deleteMember라는 id를 가지는 쿼리문을 작성한다.
- 넘겨받은 배열로부터 각각의 인덱스에 담겨있는 요소를 꺼내서 컴마 구분자와 함께 in의 괄호 안에 담아야 한다.
- 마이바티스에 마침 예시가 있다. 반복문을 돌릴 때는 foreach 태그다.
- 여기서 <where>~</where>을 복사해서 쿼리문에 붙여넣는다. 그리고 필요없는 속성들은 지운다.
- <where> 태그는 조건절을 보다 간결하게 작성할 수 있도록 도와준다.
조건이 없을 때는 WHERE 키워드를 자동으로 생략하고,
조건이 있을 때만 WHERE 키워드를 추가해준다. (값이 비어있지 않을 때만)
- 배열의 각 인덱스가 item에 담기고, item을 출력시킬 때는 #{ }으로 출력한다.
- 여기서의 collection은 자바의 List, Set, Map, 배열 등이 온다.
- collection에는 넘어온 파라미터에 대한 타입을 작성한다. 예시에서는 sql문으로 여러값이 담겨있는 list를 넘겼다.
배열을 넘긴다면 "list" 대신 "array"를 작성하면 된다.
- 각각의 인덱스에 담겨있는 값들이 순차적으로 접근한다.
- item은 변수명 역할이다. 순차적으로 접근된 값을 받는다. 변수명은 마음대로 지어도 된다.
- 순차적으로 접근할 때 인덱스도 필요하면 index 속성을 설정하면 된다.