이번 절에서는 회원 관리와 로그인에도 mybatis를 적용해보고 이를 통해 mybatis 프레임워크의 사용법에 좀 더 익숙해지는 시간을 갖는다.
1. 훈련. 회원 관리에 mybatis 적용
이번 훈련은 회원 관리에 mybatis를 적용하는 것이다. 다음 지시에 따라 구현해본다.
1) MySqlMemberDao 클래스로부터 SQL문 분리
spms.dao 패키지에 MySqlMemberDao.xml 파일을 생성한다. 그리고 MySqlMemberDao 클래스에서 SQL을 분리하여 이 SQL 맵퍼 파일에 등록한다. 프로젝트 목록과 마찬가지로 회원 목록도 이름과 이메일, 생성일에 대해 정렬이 가능해야 한다.
2) MemberDao 변경
정렬 항목에 따라 SELECT문의 ORDER BY절이 바뀌어야 한다. spms.dao.MemberDao 인터페이스에 대해 selectList() 메서드를 다음과 같이 변경한다. 매개변수에서는 정렬 정보가 넘어온다.
List<Member> selectList(HashMap<String,Object> paramMap) throws Exception;
3) MySqlMemberDao 클래스에서 SqlSession 객체를 사용하여 데이터 처리
spms.dao.MySqlMemberDao 클래스를 이전에 실습한 MySqlProjectDao 클래스처럼 변경한다. 즉 mybatis에서 제공하는 SqlSession 객체를 사용하여 멤버의 등록, 조회, 변경, 삭제를 처리한다.
4) mybatis 설정 파일에 회원 관리 SQL 맵퍼 파일의 경로 추가
spms/dao/mybatis-config.xml 파일에 SQL 맵퍼 파일 'MySqlMemberDao.xml'의 경로를 추가한다.
5) 회원 목록 컨트롤러 변경
spms.controls.MemberListController 클래스를 정렬 조건을 처리하도록 변경한다. ProjectListController 클래스를 참고한다.
6) 회원 목록 페이지의 JSP 변경
멤버 목록 페이지를 테이블 형태로 출력할 수 있도록 webapp/member/MemberList.jsp 파일을 변경한다. 회원번호, 이름, 이메일, 등록일의 테이블 컬럼 헤더에 대해 정렬 링크를 추가한다. 프로젝트 목록을 출력하는 JSP를 참고한다.
# 훈련 결과 소스
다음은 훈련 결과 소스이다. 훈련을 마친 후에 자신이 작성한 소스와 비교해본다. 결과 소스를 먼저 보고 훈련을 하면 실력이 늘지 않으니, 훈련을 먼저 수행한 다음에 결과 소스를 보기 바란다. 훈련 결과 소스 표이다.
소스 파일 | 설명 |
spms/dao/MySqlMemberDao.xml | MySqlMemberDao 클래스를 위한 SQL 맵퍼 파일 |
spms/dao/MemberDao.java | MemberDao 인터페이스 |
spms/dao/MySqlMemberDao.java | MemberDao 인터페이스 구현 클래스 |
spms/dao/mybatis-config.xml | mybatis 프레임워크 설정 파일 |
spms/controls/MemberListController.java | 회원 목록 페이지를 처리하는 페이지 컨트롤러 |
webapp/member/MemberList.jsp | 회원 목록 페이지를 생성하는 뷰 컴포넌트 |
1) 회원 관리 SQL 맵퍼 - MySqlMemberDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 2. 동적 SQL 적용 -->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="spms.dao.MemberDao">
<resultMap type="member" id="memberResultMap">
<id column="MNO" property="no"/>
<result column="MNAME" property="name"/>
<result column="EMAIL" property="email"/>
<result column="PWD" property="password"/>
<result column="CRE_DATE" property="createdDate" javaType="java.sql.Date"/>
<result column="MOD_DATE" property="modifiedDate" javaType="java.sql.Date"/>
</resultMap>
<select id="selectList" resultMap="memberResultMap" parameterType="map">
SELECT MNO, MNAME, EMAIL, CRE_DATE
FROM MEMBERS
ORDER BY
<choose>
<when test="orderCond == 'NAME_ASC'">MNAME ASC</when>
<when test="orderCond == 'NAME_DESC'">MNAME DESC</when>
<when test="orderCond == 'EMAIL_ASC'">EMAIL ASC</when>
<when test="orderCond == 'EMAIL_DESC'">EMAIL DESC</when>
<when test="orderCond == 'CREDATE_ASC'">CRE_DATE ASC</when>
<when test="orderCond == 'CREDATE_DESC'">CRE_DATE DESC</when>
<when test="orderCond == 'MNO_ASC'">MNO ASC</when>
<otherwise>MNO DESC</otherwise>
</choose>
</select>
<insert id="insert" parameterType="member">
INSERT INTO MEMBERS (MNAME, EMAIL, PWD, CRE_DATE, MOD_DATE)
VALUES (#{name}, #{email}, #{password}, now(), now())
</insert>
<select id="selectOne" resultMap="memberResultMap" parameterType="int">
SELECT MNO, MNAME, EMAIL, CRE_DATE, MOD_DATE
FROM MEMBERS
WHERE MNO = #{value}
</select>
<update id="update" parameterType="map">
UPDATE MEMBERS
<set>
<if test="name != null">MNAME = #{name},</if>
<if test="email != null">EMAIL = #{email},</if>
MOD_DATE = now()
</set>
WHERE MNO = #{no}
</update>
<delete id="delete" parameterType="int">
DELETE FROM MEMBERS
WHERE MNO = #{value}
</delete>
<select id="exist" resultMap="memberResultMap" parameterType="map">
SELECT MNO, MNAME, EMAIL, CRE_DATE, MOD_DATE
FROM MEMBERS
WHERE EMAIL = #{email} AND PWD = #{password}
</select>
</mapper>
2) MemberDao 인터페이스 - MemberDao.java
package spms.dao;
import java.util.HashMap;
import java.util.List;
import spms.vo.Member;
//MemberDao 인터페이스 정의
public interface MemberDao {
List<Member> selectList(HashMap<String,Object> paramMap) throws Exception;
int insert(Member member) throws Exception;
int delete(int no) throws Exception;
Member selectOne(int no) throws Exception;
int update(Member member) throws Exception;
Member exist(String email, String password) throws Exception;
}
3) MemberDao 구현 클래스 - MySqlMemberDao.java
package spms.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import spms.annotation.Component;
import spms.util.DBConnectionPool;
import spms.vo.Member;
//mybatis적용
@Component(value="memberDao")
public class MySqlMemberDao implements MemberDao {
//SqlSessionFactory 인터페이스
SqlSessionFactory sqlSessionFactory;
/**
* SqlSessionFactory 인터페이스 객체 주입
* @param sqlSessionFactory
*/
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
/**
* 회원 목록 조회
* @param paramMap
* @return
* @throws Exception
*/
public List<Member> selectList(HashMap<String,Object> paramMap) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
return sqlSession.selectList("spms.dao.MemberDao.selectList", paramMap);
} finally {
sqlSession.close();
}
}
/**
* 회원 등록
* @param project
* @return count
*/
public int insert(Member member) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
int count = sqlSession.insert("spms.dao.MemberDao.insert", member);
sqlSession.commit();
return count;
} finally {
sqlSession.close();
}
}
/**
* 회원 상세 정보 조회
* @param no
* @return sqlSession.selectOne("spms.dao.MemberDao.selectOne", no)
*/
public Member selectOne(int no) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
return sqlSession.selectOne("spms.dao.MemberDao.selectOne", no);
} finally {
sqlSession.close();
}
}
/**
* 회원 정보 수정
* @param member
* @return count, 0
*/
public int update(Member member) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
//원래의 회원 정보 가져옴
Member original = sqlSession.selectOne("spms.dao.MemberDao.selectOne", member.getNo());
//바뀐 값 저장할 Map 객체
Hashtable<String,Object> paramMap = new Hashtable<String,Object>();
//원래의 값과 사용자가 입력한 값 비교
if(!member.getName().equals(original.getName())) {
paramMap.put("name", member.getName());
}
if(!member.getEmail().equals(original.getEmail())) {
paramMap.put("email", member.getEmail());
}
if(paramMap.size() > 0) {//바뀐값O
paramMap.put("no", member.getNo());
int count = sqlSession.update("spms.dao.MemberDao.update", paramMap);
sqlSession.commit();
return count;
}else {//바뀐값X
return 0;
}
} finally {
sqlSession.close();
}
}
/**
* 회원 삭제
* @param no
* @return count
*/
public int delete(int no) throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
int count = sqlSession.delete("spms.dao.MemberDao.delete", no);
sqlSession.commit();
return count;
} finally {
sqlSession.close();
}
}
/**
* 회원 정보 확인
* @param email
* @param password
* @return sqlSession.selectOne("spms.dao.MemberDao.exist", paramMap)
*/
public Member exist(String email, String password) throws Exception {
HashMap<String,String> paramMap = new HashMap<String,String>();
paramMap.put("email", email);
paramMap.put("password", password);
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
return sqlSession.selectOne("spms.dao.MemberDao.exist", paramMap);
} finally {
sqlSession.close();
}
}
}
4) mybatis 설정 파일 - mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<typeAliases>
<typeAlias type="spms.vo.Project" alias="project"/>
<typeAlias type="spms.vo.Member" alias="member"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jdbc/studydb"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="spms/dao/MySqlProjectDao.xml"/>
<mapper resource="spms/dao/MySqlMemberDao.xml"/>
</mappers>
</configuration>
5) 회원 목록 페이지 컨트롤러 - MemberListController.java
package spms.controls;
import java.util.HashMap;
import java.util.Map;
import spms.annotation.Component;
import spms.bind.DataBinding;
import spms.dao.MySqlMemberDao;
@Component("/member/list.do")
public class MemberListController implements Controller, DataBinding {
//인스턴스 변수
MySqlMemberDao memberDao;
//셋터 메서드
public MemberListController setMemberDao(MySqlMemberDao memberDao) {
this.memberDao = memberDao;
return this; //셋터 메서드 쉽게 사용하기 위해 자신의 인스턴스 값 반환
}
//DataBinding 인터페이스의 구현 메서드
@Override
public Object[] getDataBinders() {
return new Object[] {"orderCond", String.class};
}
//Controller 인터페이스 구현 메서드
@Override
public String execute(Map<String, Object> model) throws Exception {
HashMap<String,Object> paramMap = new HashMap<String,Object>();
//정렬조건 전달 Map
paramMap.put("orderCond", model.get("orderCond"));
//회원 목록 데이터를 Map 객체에 저장
model.put("members", memberDao.selectList(paramMap));
//화면을 출력할 JSP 페이지의 URL 반환
return "/member/MemberList.jsp";
}
}
6) 회원 목록 뷰 컴포넌트 - MemberList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!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=UTF-8">
<title>회원 목록2</title>
</head>
<body>
<jsp:include page="/Header.jsp"/>
<h1>회원목록2</h1>
<p><a href='add.do'>신규 회원</a></p>
<table border="1">
<tr>
<th><c:choose>
<c:when test="${orderCond == 'MNO_ASC'}">
<a href="list.do?orderCond=MNO_DESC">번호↑</a>
</c:when>
<c:when test="${orderCond == 'MNO_DESC'}">
<a href="list.do?orderCond=MNO_ASC">번호↓</a>
</c:when>
<c:otherwise>
<a href="list.do?orderCond=MNO_ASC">번호︎</a>
</c:otherwise>
</c:choose></th>
<th><c:choose>
<c:when test="${orderCond == 'NAME_ASC'}">
<a href="list.do?orderCond=NAME_DESC">이름↑</a>
</c:when>
<c:when test="${orderCond == 'NAME_DESC'}">
<a href="list.do?orderCond=NAME_ASC">이름↓</a>
</c:when>
<c:otherwise>
<a href="list.do?orderCond=NAME_ASC">이름</a>
</c:otherwise>
</c:choose></th>
<th><c:choose>
<c:when test="${orderCond == 'EMAIL_ASC'}">
<a href="list.do?orderCond=EMAIL_DESC">이메일↑</a>
</c:when>
<c:when test="${orderCond == 'EMAIL_DESC'}">
<a href="list.do?orderCond=EMAIL_ASC">이메일↓</a>
</c:when>
<c:otherwise>
<a href="list.do?orderCond=EMAIL_ASC">이메일</a>
</c:otherwise>
</c:choose></th>
<th><c:choose>
<c:when test="${orderCond == 'CREDATE_ASC'}">
<a href="list.do?orderCond=CREDATE_DESC">등록일↑</a>
</c:when>
<c:when test="${orderCond == 'CREDATE_DESC'}">
<a href="list.do?orderCond=CREDATE_ASC">등록일↓</a>
</c:when>
<c:otherwise>
<a href="list.do?orderCond=CREDATE_ASC">등록일</a>
</c:otherwise>
</c:choose></th>
<th></th>
</tr>
<c:forEach var="member" items="${members}">
<tr>
<td>${member.no}</td>
<td><a href='update.do?no=${member.no}'>${member.name}</a></td>
<td>${member.email}</td>
<td>${member.createdDate}</td>
<td><a href='delete.do?no=${member.no}'>[삭제]</a></td>
</tr>
</c:forEach>
</table>
<jsp:include page="/Tail.jsp"/>
</body>
</html>
참고도서 : https://freelec.co.kr/book/1674/
[열혈강의] 자바 웹 개발 워크북
[열혈강의] 자바 웹 개발 워크북
freelec.co.kr
'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글
121. Gradle (1) | 2022.09.27 |
---|---|
120. 퍼시스턴스 프레임워크의 도입 정리 (0) | 2022.09.26 |
118. 동적 SQL의 사용 (5) (0) | 2022.09.22 |
117. 동적 SQL의 사용 (4) (0) | 2022.09.21 |
116. 동적 SQL의 사용 (3) (2) | 2022.09.20 |
댓글