관리 메뉴

거니의 velog

231129_SPRING 2 (6-2) 본문

대덕인재개발원_웹기반 애플리케이션

231129_SPRING 2 (6-2)

Unlimited00 2023. 11. 29. 08:23
package kr.or.ddit.controller.database;

public class MybatisController {

	/*
	 * [ 12장. 마이바티스 ]
	 * 
	 * 		1. 마이바티스란?
	 * 
	 * 			마이바티스는 자바 퍼시스턴스 프레임워크의 하나로 XML 서술자나 어노테이션을 사용하여 저장프로시저나 SQL문으로 객체들을 연결시킨다.
	 * 			마이바티스는 Apache 라이선스 2.0으로 배포되는 자유 소프트웨어이다.
	 * 
	 * 			# 마이바티스를 사용함으로써 얻을 수 있는 이점
	 * 			- SQL의 체계적인 관리
	 * 			- 자바 객체와 SQL 입출력 값의 투명한 바인딩
	 * 			- 동적 SQL 조합
	 * 
	 * 			# 마이바티스 설정
	 * 
	 * 				1) 의존관계 정의
	 * 				- 총 6가지 라이브러리를 등록하여 관계를 정의한다. (DatabaseConnectContoller 참고)
	 * 
	 * 				2) 스프링과 마이바티스 연결 설정
	 * 				- root-context.xml 설정(DatabaseConnectController 참고)
	 * 				- 총 3가지를 등록하여 설정한다. (추가로 Mapper를 등록하기 위한 basePackage 정보도 함께 추가할 예정
	 * 
	 * 				3) 마이바티스 설정
	 * 				- WEB-INF/mybatisAlias/mybatisAlias.xml 설정
	 * 				- 마이바티스의 위치 설정은 root-context.xml의 'sqlSessionFactory' 설정 시, property 요소로 적용
	 * 
	 * 			# 관련 테이블 생성
	 *
	 *				- board 테이블 생성
	 *				- member 테이블 생성
	 *				- member_auth 테이블 생성
	 *
	 *		2. Mapper 인터페이스
	 *
	 *			- 인터페이스의 구현을 mybatis-spring에서 자동으로 생성할 수 있다.
	 *
	 *			1) 마이바티스 구현
	 *
	 *				1-1) Mapper 인터페이스
	 *				- BoardMapper.java 생성(인터페이스)
	 *
	 *				1-2) Mapper 인터페이스와 매핑할 Mapper
	 *				- sqlmap/boardMapper_SQL.xml 생성
	 *
	 *				1-3) 게시판 구현 설명
	 *
	 *				- 게시판 컨트롤러 만들기 (crud/CrudBoardController)
	 *				- 게시판 등록 화면 컨트롤러 메소드 만들기(crudRegister:get)
	 *				- 게시판 등록 화면 만들기 (crud/register.jsp)
	 *				- 여기까지 확인
	 *
	 *				- 게시판 등록 기능 컨트롤러 메소드 만들기 (crudRegister:post)
	 *				- 게시판 등록 기능 서비스 인터페이스 메소드 만들기
	 *				- 게시판 등록 기능 서비스 클래스 메소드 만들기
	 *				- 게시판 등록 기능 Mapper 인터페이스 메소드 만들기
	 *				- 게시판 등록 기능 Mapper xml 쿼리 만들기
	 *				- 게시판 등록 완료 페이지 만들기
	 *				- 여기까지 확인
	 *
	 *				- 게시판 목록 화면 컨트롤러 메소드 만들기 (crudList:get)
	 *				- 게시판 목록 화면 서비스 인터페이스 메소드 만들기
	 *				- 게시판 목록 화면 서비스 클래스 메소드 만들기
	 *				- 게시판 목록 화면 Mapper 인터페이스 메소드 만들기
	 *				- 게시판 목록 화면 Mapper xml 쿼리 만들기
	 *				- 게시판 목록 화면 만들기 (crud/list.jsp)
	 *				- 여기까지 확인
	 *
	 *				- 게시판 상세 화면 컨트롤러 메소드 만들기 (crudRead:get)
	 *				- 게시판 상세 화면 서비스 인터페이스 메소드 만들기
	 *				- 게시판 상세 화면 서비스 클래스 메소드 만들기
	 *				- 게시판 상세 화면 Mapper 인터페이스 메소드 만들기
	 *				- 게시판 상세 화면 Mapper xml 쿼리 만들기
	 *				- 게시판 상세 화면 만들기 (crud/read.jsp)
	 *				- 여기까지 확인!
	 *
	 *				- 게시판 수정 화면 컨트롤러 메소드 만들기 (crudModify:get)
	 *				- 게시판 수정 화면 서비스 인터페이스 메소드 만들기
	 *				- 게시판 수정 화면 서비스 클래스 메소드 만들기
	 *				- 게시판 수정 화면 Mapper 인터페이스 메소드 만들기
	 *				- 게시판 수정 화면 Mapper xml 쿼리 만들기
	 *				- 게시판 수정 화면 만들기 (crud/register.jsp)
	 *				- 게시판 수정 기능 컨트롤러 메소드 만들기 (crudModify:post)
	 *				- 게시판 수정 기능 서비스 인터페이스 메소드 만들기
	 *				- 게시판 수정 기능 서비스 클래스 메소드 만들기
	 *				- 게시판 수정 기능 Mapper 인터페이스 메소드 만들기
	 *				- 게시판 수정 기능 Mapper xml 쿼리 만들기
	 *				- 여기까지 확인!
	 *
	 *				- 게시판 삭제 기능 컨트롤러 메소드 만들기 (crudRemove:post)
	 *				- 게시판 삭제 기능 서비스 인터페이스 메소드 만들기
	 *				- 게시판 삭제 기능 서비스 클래스 메소드 만들기
	 *				- 게시판 삭제 기능 Mapper 인터페이스 메소드 만들기
	 *				- 게시판 삭제 기능 Mapper xml 쿼리 만들기
	 *				- 여기까지 확인!
	 *
	 *				- 게시판 목록 화면 검색 페이지 추가(crud/board/list.jsp)
	 *				- 게시판 검색 기능 컨트롤러 메소드 추가(crudSearch:post)
	 *				- 게시판 검색 기능 서비스 인터페이스 메소드 추가
	 *				- 게시판 검색 기능 서비스 클래스 메소드 추가
	 *				- 게시판 검색 기능 Mapper 메소드 추가
	 *				- 게시판 검색 기능 Mapper xml 쿼리 추가
	 *				- 여기까지 확인
	 *
	 *				- 기본 CRUD 끝
	 *
	 *		3. 별칭 적용
	 *
	 *			- TypeAlias로 맵핑 파일에서 반복적으로 사용할 패키지의 이름을 정의한다.
	 *
	 *			1) 마이바티스 설정
	 *
	 *				1-1) mybatisAlias.xml 설정
	 *				- typeAlias 설정을 한다.
	 *
	 *				1-2) boardMapper_SQL.xml의 type의 설정을 별칭으로 설정
	 *				- mybatisAlias가 설정되어 있지 않는 경우엔 타입으로 설정하고자 하는 타입 형태를
	 *					패키지명이 포함되어 있는 구조로 설정해야 한다.
	 *				- 쿼리 태그에 각각 셋팅한 패키지명 대신에 alias로 설정한 별칭으로 대체한다.
	 *
	 *		4. '_'로 구분된 컬럼명 자동 매핑
	 *
	 *			- 마이바티스 설정의 mapUnderscoreToCamelCase 프로퍼티 값을 true로 지정하면
	 *				'_'로 구분된 컬럼명을 소문자 낙타표기법의 프로퍼티명으로 자동 매핑할 수 있다.
	 *
	 *			- '_'가 포함되어 있는 데이터베이스 컬럼명을 Camel 기법 셋팅으로 인해서 board_no가 boardNo로 처리된다.
	 *
	 *			1) 마이바티스 설정
	 *
	 *				1-1) mybatisAlias.xml 설정
	 *					<settings>
	 *						<setting name="mapUnderscoreToCamelCase" value="true" />
	 *					</settings>
	 *
	 *				1-2) 매핑 파일 수정(기존 Mapper xml에 설정된 컬럼은 board_no와 같은 형태의 파라미터 값으로 되어 있다면 수정)
	 *					- as boardNo, as regDate로 컬럼명을 대체하는 쿼리가 등록되어 있을 시 삭제
	 *						> as boardNo와 같은 별칭을 따로 정하지 않아도 알아서 매핑되므로
	 *
	 *		5. 기본키 취득
	 *
	 *			- 마이바티스는 useGeneratedKeys 속성을 이용하여 insert할 때 데이터베이스 측에서 채번된 기본키를 취득할 수 있다.
	 *
	 *			1) 마이바티스 설정
	 *
	 *				1-1) 매핑 파일 수정(boardMapper_SQL.xml)
	 *				- create 부분의 속성 추가
	 *					> useGeneratedKeys = "true" (insert 태그 내 속성으로 추가)
	 *					<selectKey keyProperty="boardNo" resultType="int" order="BEFORE">
							select seq_board.nextval from dual
						</selectKey>
						> insert into ......
	 *
	 *				아래 insert 쿼리가 실행 되기 전, selectKey 태그 내에 있는 쿼리가 먼저 실행되어 최신의 boardNo를 생성하고
	 *				생성된 boardNo를 sql쿼리가 담겨 있는 insert 태그까지 넘어올 때, 넘겨주고 있는 파라미터(board)의
	 *				property인 boardNo에 셋팅된다.
	 *				셋팅된 boardNo를 아래에서 insert 시 등록 값으로 사용하고 board라는 자바빈즈 객체에 담겨 최종 컨트롤러까지
	 *				넘어가서 넘겨받은 boardNo를 이용한 상세보기 페이지로의 이동이 가능하다.
	 *
	 *				*** seq_board.nextval 대신 현재의 seq 번호를 가져오기 위해 currval를 사용하게 되는 경우가 있다.
	 *				이 때, 주의사항이 있다.
	 *
	 *					- select seq_board.currval from dual
	 *					> 위 select 쿼리를 사용 시, currval을 사용하는 데 있어서 사용 불가에 대한 에러가 발생할 수 있다.
	 *						currval을 사용할 때는 select seq.board.nextval from dual로 먼저 최초로 실행 후,
	 *						같은 세션 내에서의 실행이 이뤄지지 않았기 때문에 currval로 데이터를 가져오는데 에러가 발생한다.
	 *
	 *					# 그럼에도 나는 가져와야겠다! 다 필요 없고 그냥 줘!
	 *					> select last_number from user_sequence where sequence_name = '시퀀스명'
	 *					> select last_number from user_sequence where sequence_name = 'seq_board'
	 *						쿼리를 이용하여 가져오면 된다. (권고사항 아님 절대)
	 *
	 *				1-2) 컨트롤러 메서드에서 curdRegister 부분의 등록이 되고 나서 리턴되는 방향성을 수정
	 *
	 *					- 완료 후 성공 페이지로 이동하지만, 넘겨받은 boardNo 즉, 게시글을 등록 후 생성된 
	 *						최근 글번호(boardNo)가 있으므로 글번호를 이용하여 상세보기 페이지로의 이동이 가능하다.
	 *						성공 후 결과페이지(success)로 넘어간 후 목록으로 전환해도 되고, 최신 게시글 번호를 이용한 
	 *						상세보기 페이지로의 이동으로 프로세스를 전환해도 무방! (자유롭게)
	 *
	 *		6. 동적 SQL
	 *
	 *			- 마이바티스는 동적 SQL을 조립하는 구조로 지원하고 있으며, SQL 조립 규칙을 매핑 파일에 정의할 수 있다.
	 *
	 *			1) 동적으로 SQL을 조립하기 위한 SQL요소
	 *				- <where>
	 *					> where 절 앞 뒤에 내용을 더 추가하거나 삭제할 때 사용하는 요소
	 *				- <if>
	 *					> 조건을 만족할 때만 SQL을 조립할 수 있게 만드는 요소
	 *				- <choose>
	 *					> 여러 선택 항목에서 조건에 만족할 때만 SQL을 조립할 수 있게 만드는 요소
	 *				- <forEach>
	 *					> 컬렉션이나 배열에 대해 반복 처리를 하기 위한 요소
	 *				- <set>
	 *					> set 절 앞뒤에 내용을 더 추가하거나 삭제할 때 사용하는 요소
	 *
	 *		7. 일대다 관계 테이블 매핑
	 *
	 *			- 마이바티스 기능을 활용하여 매핑 파일을 적절하게 정의하면 일대다 관계 테이블 매핑을 쉽게 처리할 수 있다.
	 *
	 *			1) 게시판 구현 설명
	 *
	 *				- 회원 등록 화면 컨트롤러 만들기 (crud/CrudMemberController)
	 *				- 회원 등록 화면 컨트롤러 메소드 만들기
	 *				- 회원 등록 화면 만들기(crud/member/register.jsp)
	 *				- 여기까지 확인
	 *
	 *				- 회원 등록 기능 컨트롤러 메소드 만들기 (crudMemberRegister:post)
	 *				- 회원 등록 기능 인터페이스 메소드 만들기
	 *				- 회원 등록 기능 클래스 메소드 만들기
	 *				- 회원 등록 기능 Mapper 인터페이스 메소드 만들기
	 *				- 회원 등록 기능 Mapper xml 쿼리 만들기
	 *				- 회원 등록 완료 페이지 만들기 (crud/member/success.jsp)
	 *				- 여기까지 확인
	 *
	 *				- 회원 목록 화면 컨트롤러 메소드 만들기(crudMemberList:get)
	 *				- 회원 목록 화면 인터페이스 메소드 만들기
	 *				- 회원 목록 화면 클래스 메소드 만들기
	 *				- 회원 목록 화면 Mapper 인터페이스 메소드 만들기
	 *				- 회원 목록 화면 Mapper xml 쿼리 만들기
	 *				- 회원 목록 화면 페이지 만들기(crud/member/list.jsp)
	 *				- 여기까지 확인
	 *
	 *				- 회원 상세화면 컨트롤러 메소드 만들기 (crudMemberRead:get)
	 *				- 회원 상세화면 인터페이스 메소드 만들기
	 *				- 회원 상세화면 클래스 메소드 만들기
	 *				- 회원 상세화면 Mapper 인터페이스 메소드 만들기
	 *				- 회원 상세화면 Mapper xml 쿼리 만들기
	 *				- 회원 상세화면 페이지 만들기 (crud/member/read.jsp)
	 *				- 여기까지 확인
	 *
	 *				- 회원 수정 화면 컨트롤러 메소드 만들기 (crudMemberModify:get)
	 *				- 회원 수정 화면 서비스 인터페이스 메소드 만들기
	 *				- 회원 수정 화면 서비스 클래스 메소드 만들기
	 *				- 회원 수정 화면 Mapper 인터페이스 메소드 만들기
	 *				- 회원 수정 화면 Mapper xml 쿼리 만들기
	 *				- 회원 수정 화면 페이지 만들기(crud/member/modify.jsp)
	 *				- 여기까지 확인
	 *
	 *				- 회원 수정 기능 컨트롤러 메소드 만들기 (crudMemberModify:post)
	 *				- 회원 수정 기능 서비스 인터페이스 메소드 만들기
	 *				- 회원 수정 기능 서비스 클래스 메소드 만들기
	 *				- 회원 수정 기능 Mapper 인터페이스 메소드 만들기
	 *				- 회원 수정 기능 Mapper xml 쿼리 만들기
	 *				- 여기까지 확인
	 *
	 *				- 회원 삭제 기능 컨트롤러 메소드 만들기 (crudMemberDelete:post)
	 *				- 회원 삭제 기능 서비스 인터페이스 메소드 만들기
	 *				- 회원 삭제 기능 서비스 클래스 메소드 만들기
	 *				- 회원 삭제 기능 Mapper 인터페이스 메소드 만들기
	 *				- 회원 삭제 기능 Mapper xml 쿼리 만들기
	 *				- 여기까지 확인
	 */
	
}

package kr.or.ddit.controller.crud;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/crud/member")
public class CrudMemberController {

	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String crudMemberRegisterForm() {
		log.info("crudMemberRegisterForm() 실행...!");
		return "/crud/member/register";
	}
	
}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>CRUD MEMBER REGISTER</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		
		<h2>REGISTER</h2>
		<form action="/crud/member/register" method="post" id="member" name="member">
			<table border="1">
				<tr>
					<td>userId</td>
					<td>
						<input type="text" name="userId" id="userId" />
					</td>
				</tr>
				<tr>
					<td>userPw</td>
					<td>
						<input type="text" name="userPw" id="userPw" />
					</td>
				</tr>
				<tr>
					<td>userName</td>
					<td>
						<input type="text" name="userName" id="userName" />
					</td>
				</tr>
			</table>
			<div>
				<button type="button" id="registerBtn">register</button>
				<button type="button" id="listBtn">list</button>
			</div>
		</form>
		
	</body>
	<script type="text/javascript">
		$(function(){
			var member = $("#member"); // form
			var registerBtn = $("#registerBtn");
			var listBtn = $("#listBtn");
			
			registerBtn.on("click", function(){
				var userId = $("#userId").val();
				var userPw = $("#userPw").val();
				var userName = $("#userName").val();
				
				if(!userId) {
					alert("아이디를 입력해 주세요!");
					return false;
				}
				if(!userPw) {
					alert("비밀번호를 입력해 주세요!");
					return false;
				}
				if(!userName) {
					alert("이름을 입력해 주세요!");
					return false;
				}
				
				member.submit(); // 정상적인 데이터가 입력되었을 때 submit 한다(서버 전송).
			});
			
			listBtn.on("click", function(){
				location.href = "/crud/member/list";
			});
		});
	</script>
</html>

- http://localhost/crud/member/register

* 회원 정보 1명 : 권한 1개(ROLE_XXX) 최대 3개까지 권한을 가져갈 수 있다.

* 수정 기능 시에는 일대다에 해당하는, 한 명의 회원이 여러 권한을 수정할 수 있게 함.

* 두 테이블을 조인하여 상세 보기를 작성. 회원 테이블만 조회하지 않는다. MemberVO 안에 매핑시킬 것임.


package kr.or.ddit.vo.crud;

import java.util.Date;
import java.util.List;

import lombok.Data;

@Data
public class CrudMember {

	private int userNo;
	private String userId;
	private String userPw;
	private String userName;
	private Date regDate;
	private Date updDate;
	private List<CrudMemberAuth> authList;
	
}
package kr.or.ddit.vo.crud;

import lombok.Data;

@Data
public class CrudMemberAuth {

	private int userNo;
	private String auth;
	
}

package kr.or.ddit.service;

import kr.or.ddit.vo.crud.CrudMember;

public interface IMemberService {

	public void register(CrudMember member);

}
package kr.or.ddit.service.impl;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.IMemberMapper;
import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

@Service
public class MemberServiceImpl implements IMemberService {

	@Inject
	private IMemberMapper mapper;
	
	@Override
	public void register(CrudMember member) {
		// 회원 1명의 정보를 등록 시, 하나의 권한을 가질 수 있다.
		mapper.create(member); // 회원정보 1명의 데이터를 등록
		
		// 등록된 회원정보를 이용해서 권한을 등록
		CrudMemberAuth memberAuth = new CrudMemberAuth();
		memberAuth.setUserNo(member.getUserNo());
		memberAuth.setAuth("ROLE_USER");
		
		mapper.createAuth(memberAuth);
	}

}

package kr.or.ddit.mapper;

import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

public interface IMemberMapper {

	public void create(CrudMember member);
	public void createAuth(CrudMemberAuth memberAuth);

}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.IMemberMapper">
	
	<insert id="create" parameterType="crudMember" useGeneratedKeys="true">
		<selectKey keyProperty="userNo" resultType="int" order="BEFORE">
			select seq_member.nextval from dual
		</selectKey>
		insert into member (
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		) values (
			#{userNo}, #{userId}, #{userPw}, #{userName}, sysdate, sysdate
		)
	</insert>
	
	<insert id="createAuth" parameterType="crudMember">
		insert into member_auth (
			user_no, auth
		) values (
			#{userNo}, #{auth}
		)
	</insert>
	
</mapper>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	
	<!--  
		[마이바티스] 스프링에서 "_"를 사용한 컬럼명 사용 시(BOOK 테이블의 BOOK_ID와 같은 컬럼)
		카멜케이스로 읽어주는 역할(bookId와 같이)
		
		ex) 테이블 컬럼명이 member_id인 경우 jsp 화면 단에서 이 값을 사용시 memberId로 사용할 수 있다.
	-->
	<settings>
		<setting name="mapUnderscoreToCamelCase" value="true"/>
	</settings>
	
	<typeAliases>
		<typeAlias type="kr.or.ddit.vo.Board" alias="board"/>
		<typeAlias type="kr.or.ddit.vo.crud.CrudMember" alias="crudMember"/>
		<typeAlias type="kr.or.ddit.vo.crud.CrudMemberAuth" alias="crudMemberAuth"/>
	</typeAliases>
	
</configuration>

package kr.or.ddit.controller.crud;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/crud/member")
public class CrudMemberController {

	@Inject
	private IMemberService service;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String crudMemberRegisterForm() {
		log.info("crudMemberRegisterForm() 실행...!");
		return "/crud/member/register";
	}
	
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String crudMemberRegister(CrudMember member, Model model) {
		log.info("crudMemberRegister() 실행...!");
		service.register(member);
		model.addAttribute("msg", "등록이 완료되었습니다.");
		return "/crud/member/success";
	}
	
}

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>CRUD MEMBER SUCCESS</title>
	</head>
	<body>
		
		<h2>${msg }</h2>
		<a href="/crud/member/list">목록</a>
		
	</body>
</html>

- http://localhost/crud/member/register


package kr.or.ddit.controller.crud;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/crud/member")
public class CrudMemberController {

	@Inject
	private IMemberService service;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String crudMemberRegisterForm() {
		log.info("crudMemberRegisterForm() 실행...!");
		return "/crud/member/register";
	}
	
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String crudMemberRegister(CrudMember member, Model model) {
		log.info("crudMemberRegister() 실행...!");
		service.register(member);
		model.addAttribute("msg", "등록이 완료되었습니다.");
		return "/crud/member/success";
	}
	
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String crudMemberList(Model model) {
		log.info("crudMemberList() 실행...!");
		List<CrudMember> memberList = service.list();
		model.addAttribute("memberList", memberList);
		return "/crud/member/list";
	}
	
}
package kr.or.ddit.service;

import java.util.List;

import kr.or.ddit.vo.crud.CrudMember;

public interface IMemberService {

	public void register(CrudMember member);
	public List<CrudMember> list();

}
package kr.or.ddit.service.impl;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.IMemberMapper;
import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

@Service
public class MemberServiceImpl implements IMemberService {

	@Inject
	private IMemberMapper mapper;
	
	@Override
	public void register(CrudMember member) {
		// 회원 1명의 정보를 등록 시, 하나의 권한을 가질 수 있다.
		mapper.create(member); // 회원정보 1명의 데이터를 등록
		
		// 등록된 회원정보를 이용해서 권한을 등록
		CrudMemberAuth memberAuth = new CrudMemberAuth();
		memberAuth.setUserNo(member.getUserNo());
		memberAuth.setAuth("ROLE_USER");
		
		mapper.createAuth(memberAuth);
	}

	@Override
	public List<CrudMember> list() {
		return mapper.list();
	}

}
package kr.or.ddit.mapper;

import java.util.List;

import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

public interface IMemberMapper {

	public void create(CrudMember member);
	public void createAuth(CrudMemberAuth memberAuth);
	public List<CrudMember> list();

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.IMemberMapper">
	
	<insert id="create" parameterType="crudMember" useGeneratedKeys="true">
		<selectKey keyProperty="userNo" resultType="int" order="BEFORE">
			select seq_member.nextval from dual
		</selectKey>
		insert into member (
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		) values (
			#{userNo}, #{userId}, #{userPw}, #{userName}, sysdate, sysdate
		)
	</insert>
	
	<insert id="createAuth" parameterType="crudMemberAuth">
		insert into member_auth (
			user_no, auth
		) values (
			#{userNo}, #{auth}
		)
	</insert>
	
	<select id="list" resultType="crudMember">
		select 
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		from member 
		order by user_no desc
	</select>
	
</mapper>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>CRUD MEMBER LIST</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		
		<h2>LIST</h2>
		<a href="/crud/member/register">등록</a>
		
		<table border="1">
			<tr>
				<td align="center" width="60">번호</td>
				<td align="center" width="80">아이디</td>
				<td align="center" width="50">비밀번호</td>
				<td align="center" width="50">사용자명</td>
				<td align="center" width="180">작성일</td>
			</tr>
			<c:choose>
				<c:when test="${empty memberList }">
					<td colspan="5">조회하신 회원 정보가 존재하지 않습니다.</td>
				</c:when>
				<c:otherwise>
					<c:forEach items="${memberList }" var="member">
						<tr>
							<td align="center">${member.userNo }</td>
							<td align="center">
								<a href="/crud/member/read?userNo=${member.userNo }">
									${member.userId }
								</a>
							</td>
							<td align="left">${member.userPw }</td>
							<td align="right">${member.userName }</td>
							<td align="center">
								<fmt:formatDate value="${member.regDate }" pattern="yyyy-MM-dd HH:mm"/>
							</td>
						</tr>
					</c:forEach>
				</c:otherwise>
			</c:choose>
		</table>
		
	</body>
</html>

- http://localhost/crud/member/list


package kr.or.ddit.controller.crud;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/crud/member")
public class CrudMemberController {

	@Inject
	private IMemberService service;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String crudMemberRegisterForm() {
		log.info("crudMemberRegisterForm() 실행...!");
		return "/crud/member/register";
	}
	
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String crudMemberRegister(CrudMember member, Model model) {
		log.info("crudMemberRegister() 실행...!");
		service.register(member);
		model.addAttribute("msg", "등록이 완료되었습니다.");
		return "/crud/member/success";
	}
	
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String crudMemberList(Model model) {
		log.info("crudMemberList() 실행...!");
		List<CrudMember> memberList = service.list();
		model.addAttribute("memberList", memberList);
		return "/crud/member/list";
	}
	
	@RequestMapping(value = "/read", method = RequestMethod.GET)
	public String crudMemberRead(int userNo, Model model) {
		log.info("crudMemberRead() 실행...!");
		CrudMember member = service.read(userNo);
		model.addAttribute("member", member);
		return "/crud/member/read";
	}
	
}
package kr.or.ddit.service;

import java.util.List;

import kr.or.ddit.vo.crud.CrudMember;

public interface IMemberService {

	public void register(CrudMember member);
	public List<CrudMember> list();
	public CrudMember read(int userNo);

}
package kr.or.ddit.service.impl;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.IMemberMapper;
import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

@Service
public class MemberServiceImpl implements IMemberService {

	@Inject
	private IMemberMapper mapper;
	
	@Override
	public void register(CrudMember member) {
		// 회원 1명의 정보를 등록 시, 하나의 권한을 가질 수 있다.
		mapper.create(member); // 회원정보 1명의 데이터를 등록
		
		// 등록된 회원정보를 이용해서 권한을 등록
		CrudMemberAuth memberAuth = new CrudMemberAuth();
		memberAuth.setUserNo(member.getUserNo());
		memberAuth.setAuth("ROLE_USER");
		
		mapper.createAuth(memberAuth);
	}

	@Override
	public List<CrudMember> list() {
		return mapper.list();
	}

	@Override
	public CrudMember read(int userNo) {
		return mapper.read(userNo);
	}

}
package kr.or.ddit.mapper;

import java.util.List;

import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

public interface IMemberMapper {

	public void create(CrudMember member);
	public void createAuth(CrudMemberAuth memberAuth);
	public List<CrudMember> list();
	public CrudMember read(int userNo);

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.IMemberMapper">
	
	<resultMap type="crudMember" id="memberMap">
		<id property="userNo" column="user_no" />
		<result property="userNo" column="user_no" />
		<result property="userId" column="user_id" />
		<result property="userPw" column="user_pw" />
		<result property="userName" column="user_name" />
		<result property="regDate" column="reg_date" />
		<result property="updDate" column="upd_date" />
		<collection property="authList" resultMap="authMap" />
	</resultMap>
	
	<resultMap type="crudMemberAuth" id="authMap">
		<result property="userNo" column="user_no" />
		<result property="auth" column="auth" />
	</resultMap>
	
	<insert id="create" parameterType="crudMember" useGeneratedKeys="true">
		<selectKey keyProperty="userNo" resultType="int" order="BEFORE">
			select seq_member.nextval from dual
		</selectKey>
		insert into member (
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		) values (
			#{userNo}, #{userId}, #{userPw}, #{userName}, sysdate, sysdate
		)
	</insert>
	
	<insert id="createAuth" parameterType="crudMemberAuth">
		insert into member_auth (
			user_no, auth
		) values (
			#{userNo}, #{auth}
		)
	</insert>
	
	<select id="list" resultType="crudMember">
		select 
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		from member 
		order by user_no desc
	</select>
	
	<select id="read" parameterType="int" resultMap="memberMap">
		select 
			m.user_no, user_id, user_pw, user_name, reg_date, upd_date, 
			auth 
		from member m left outer join member_auth ma on(m.user_no = ma.user_no) 
		where m.user_no = #{userNo}
	</select>
	
</mapper>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>CRUD MEMBER READ</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		
		<h2>READ</h2>
		<table border="1">
			<tr>
				<td>userId</td>
				<td>${member.userId }</td>
			</tr>
			<tr>
				<td>userName</td>
				<td>${member.userName }</td>
			</tr>
			<tr>
				<td>auth - 1</td>
				<td>${member.authList[0].auth }</td>
			</tr>
			<tr>
				<td>auth - 2</td>
				<td>${member.authList[1].auth }</td>
			</tr>
			<tr>
				<td>auth - 3</td>
				<td>${member.authList[2].auth }</td>
			</tr>
		</table>
		
	</body>
	<script type="text/javascript">
		$(function(){
			
		});
	</script>
</html>

- http://localhost/crud/member/read?userNo=1


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>CRUD MEMBER READ</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		
		<h2>READ</h2>
		<table border="1">
			<tr>
				<td>userId</td>
				<td>${member.userId }</td>
			</tr>
			<tr>
				<td>userName</td>
				<td>${member.userName }</td>
			</tr>
			<tr>
				<td>auth - 1</td>
				<td>${member.authList[0].auth }</td>
			</tr>
			<tr>
				<td>auth - 2</td>
				<td>${member.authList[1].auth }</td>
			</tr>
			<tr>
				<td>auth - 3</td>
				<td>${member.authList[2].auth }</td>
			</tr>
		</table>
		<form action="/crud/member/remove" id="delForm" name="delForm" method="post">
			<input type="hidden" name="userNo" value="${member.userNo }" />
		</form>
		<div>
			<button type="button" id="modifyBtn">Modify</button>
			<button type="button" id="removeBtn">Remove</button>
			<button type="button" id="listBtn">List</button>
		</div>
	</body>
	<script type="text/javascript">
		$(function(){
			var delForm = $("#delForm");
			var modifyBtn = $("#modifyBtn");
			var removeBtn = $("#removeBtn");
			var listBtn = $("#listBtn");
			
			modifyBtn.on("click", function(){
				delForm.attr("action", "/crud/member/modify");
				delForm.attr("method", "get");
				delForm.submit();
			});
			
			removeBtn.on("click", function(){
				if(confirm("정말로 삭제하시겠습니까?")) {
					delForm.submit();
				}
			});
			
			listBtn.on("click", function(){
				location.href = "/crud/member/list";
			});
		});
	</script>
</html>
package kr.or.ddit.controller.crud;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/crud/member")
public class CrudMemberController {

	@Inject
	private IMemberService service;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String crudMemberRegisterForm() {
		log.info("crudMemberRegisterForm() 실행...!");
		return "/crud/member/register";
	}
	
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String crudMemberRegister(CrudMember member, Model model) {
		log.info("crudMemberRegister() 실행...!");
		service.register(member);
		model.addAttribute("msg", "등록이 완료되었습니다.");
		return "/crud/member/success";
	}
	
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String crudMemberList(Model model) {
		log.info("crudMemberList() 실행...!");
		List<CrudMember> memberList = service.list();
		model.addAttribute("memberList", memberList);
		return "/crud/member/list";
	}
	
	@RequestMapping(value = "/read", method = RequestMethod.GET)
	public String crudMemberRead(int userNo, Model model) {
		log.info("crudMemberRead() 실행...!");
		CrudMember member = service.read(userNo);
		model.addAttribute("member", member);
		return "/crud/member/read";
	}
	
	@RequestMapping(value = "/modify", method = RequestMethod.GET)
	public String crudMemberModifyForm(int userNo, Model model) {
		log.info("crudMemberModifyForm() 실행...!");
		CrudMember member = service.read(userNo);
		model.addAttribute("member", member);
		return "/crud/member/modify";
	}
	
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>CRUD MEMBER MODIFY</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		
		<h2>MODIFY</h2>
		<form action="/crud/member/modify" method="post" id="member" name="member">
			<input type="hidden" id="userNo" name="userNo" value="${member.userNo }" />
			<table border="1">
				<tr>
					<td>userId</td>
					<td>
						<input type="text" name="userId" value="${member.userId }" readonly="readonly" />
					</td>
				</tr>
				<tr>
					<td>userName</td>
					<td>
						<input type="text" id="userName" name="userName" value="${member.userName }" />
					</td>
				</tr>
				<tr>
					<td>auth - 1</td>
					<td>
						<select name="authList[0].auth">
							<option value="">---선택---</option>
							<option value="ROLE_USER" <c:if test="${member.authList[0].auth eq 'ROLE_USER' }">selected</c:if>>사용자</option>
							<option value="ROLE_MEMBER" <c:if test="${member.authList[0].auth eq 'ROLE_MEMBER' }">selected</c:if>>회원</option>
							<option value="ROLE_ADMIN" <c:if test="${member.authList[0].auth eq 'ROLE_ADMIN' }">selected</c:if>>관리자</option>
						</select>
					</td>
				</tr>
				<tr>
					<td>auth - 2</td>
					<td>
						<select name="authList[1].auth">
							<option value="">---선택---</option>
							<option value="ROLE_USER" <c:if test="${member.authList[1].auth eq 'ROLE_USER' }">selected</c:if>>사용자</option>
							<option value="ROLE_MEMBER" <c:if test="${member.authList[1].auth eq 'ROLE_MEMBER' }">selected</c:if>>회원</option>
							<option value="ROLE_ADMIN" <c:if test="${member.authList[1].auth eq 'ROLE_ADMIN' }">selected</c:if>>관리자</option>
						</select>
					</td>
				</tr>
				<tr>
					<td>auth - 3</td>
					<td>
						<select name="authList[2].auth">
							<option value="">---선택---</option>
							<option value="ROLE_USER" <c:if test="${member.authList[2].auth eq 'ROLE_USER' }">selected</c:if>>사용자</option>
							<option value="ROLE_MEMBER" <c:if test="${member.authList[2].auth eq 'ROLE_MEMBER' }">selected</c:if>>회원</option>
							<option value="ROLE_ADMIN" <c:if test="${member.authList[2].auth eq 'ROLE_ADMIN' }">selected</c:if>>관리자</option>
						</select>
					</td>
				</tr>
			</table>
			<div>
				<button type="button" id="modifyBtn">Modify</button>
				<button type="button" id="cancelBtn">Cancel</button>
			</div>
		</form>		
		
	</body>
	<script type="text/javascript">
		$(function(){
			var member = $("#member");
			var modifyBtn = $("#modifyBtn");
			var cancelBtn = $("#cancelBtn");
			
			modifyBtn.on("click", function(){
				var userName = $("#userName").val();
				
				if(!userName) {
					alert("이름을 입력해주세요!");
					return false;
				}
				
				member.submit();
			});
			
			cancelBtn.on("click", function(){
				location.href = "/crud/member/read?userNo=${member.userNo}";
			});
		});
	</script>
</html>

- http://localhost/crud/member/modify?userNo=1


package kr.or.ddit.controller.crud;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/crud/member")
public class CrudMemberController {

	@Inject
	private IMemberService service;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String crudMemberRegisterForm() {
		log.info("crudMemberRegisterForm() 실행...!");
		return "/crud/member/register";
	}
	
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String crudMemberRegister(CrudMember member, Model model) {
		log.info("crudMemberRegister() 실행...!");
		service.register(member);
		model.addAttribute("msg", "등록이 완료되었습니다.");
		return "/crud/member/success";
	}
	
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String crudMemberList(Model model) {
		log.info("crudMemberList() 실행...!");
		List<CrudMember> memberList = service.list();
		model.addAttribute("memberList", memberList);
		return "/crud/member/list";
	}
	
	@RequestMapping(value = "/read", method = RequestMethod.GET)
	public String crudMemberRead(int userNo, Model model) {
		log.info("crudMemberRead() 실행...!");
		CrudMember member = service.read(userNo);
		model.addAttribute("member", member);
		return "/crud/member/read";
	}
	
	@RequestMapping(value = "/modify", method = RequestMethod.GET)
	public String crudMemberModifyForm(int userNo, Model model) {
		log.info("crudMemberModifyForm() 실행...!");
		CrudMember member = service.read(userNo);
		model.addAttribute("member", member);
		return "/crud/member/modify";
	}
	
	@RequestMapping(value = "/modify", method = RequestMethod.POST)
	public String crudMemberModify(CrudMember member, Model model) {
		log.info("crudMemberModify() 실행...!");
		service.modify(member);
		model.addAttribute("msg", "수정이 완료되었습니다.");
		return "/crud/member/success";
	}
	
}
package kr.or.ddit.service;

import java.util.List;

import kr.or.ddit.vo.crud.CrudMember;

public interface IMemberService {

	public void register(CrudMember member);
	public List<CrudMember> list();
	public CrudMember read(int userNo);
	public void modify(CrudMember member);

}
package kr.or.ddit.service.impl;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.IMemberMapper;
import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

@Service
public class MemberServiceImpl implements IMemberService {

	@Inject
	private IMemberMapper mapper;
	
	@Override
	public void register(CrudMember member) {
		// 회원 1명의 정보를 등록 시, 하나의 권한을 가질 수 있다.
		mapper.create(member); // 회원정보 1명의 데이터를 등록
		
		// 등록된 회원정보를 이용해서 권한을 등록
		CrudMemberAuth memberAuth = new CrudMemberAuth();
		memberAuth.setUserNo(member.getUserNo());
		memberAuth.setAuth("ROLE_USER");
		
		mapper.createAuth(memberAuth);
	}

	@Override
	public List<CrudMember> list() {
		return mapper.list();
	}

	@Override
	public CrudMember read(int userNo) {
		return mapper.read(userNo);
	}

	@Override
	public void modify(CrudMember member) {
		// 1) 일반 회원에 대한 데이터를 수정
		mapper.modify(member);
		// 2) 권한을 수정
		//		-> 회원번호에 대한 권한 모두를 삭제
		int userNo = member.getUserNo();
		mapper.deleteAuth(userNo);
		//		-> 새롭게 수정될 권한들을 insert
		List<CrudMemberAuth> authList = member.getAuthList();
		for(int i = 0; i < authList.size(); i++) {
			CrudMemberAuth memberAuth = authList.get(i);
			String auth = memberAuth.getAuth();
			if(auth == null) {
				continue;
			}
			if(auth.trim().length() == 0) {
				continue;
			}
			memberAuth.setUserNo(userNo);
			mapper.createAuth(memberAuth);
		}
	}

}
package kr.or.ddit.mapper;

import java.util.List;

import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

public interface IMemberMapper {

	public void create(CrudMember member);
	public void createAuth(CrudMemberAuth memberAuth);
	public List<CrudMember> list();
	public CrudMember read(int userNo);
	public void modify(CrudMember member);
	public void deleteAuth(int userNo);

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.IMemberMapper">
	
	<resultMap type="crudMember" id="memberMap">
		<id property="userNo" column="user_no" />
		<result property="userNo" column="user_no" />
		<result property="userId" column="user_id" />
		<result property="userPw" column="user_pw" />
		<result property="userName" column="user_name" />
		<result property="regDate" column="reg_date" />
		<result property="updDate" column="upd_date" />
		<collection property="authList" resultMap="authMap" />
	</resultMap>
	
	<resultMap type="crudMemberAuth" id="authMap">
		<result property="userNo" column="user_no" />
		<result property="auth" column="auth" />
	</resultMap>
	
	<insert id="create" parameterType="crudMember" useGeneratedKeys="true">
		<selectKey keyProperty="userNo" resultType="int" order="BEFORE">
			select seq_member.nextval from dual
		</selectKey>
		insert into member (
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		) values (
			#{userNo}, #{userId}, #{userPw}, #{userName}, sysdate, sysdate
		)
	</insert>
	
	<insert id="createAuth" parameterType="crudMemberAuth">
		insert into member_auth (
			user_no, auth
		) values (
			#{userNo}, #{auth}
		)
	</insert>
	
	<select id="list" resultType="crudMember">
		select 
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		from member 
		order by user_no desc
	</select>
	
	<select id="read" parameterType="int" resultMap="memberMap">
		select 
			m.user_no, user_id, user_pw, user_name, reg_date, upd_date, 
			auth 
		from member m left outer join member_auth ma on(m.user_no = ma.user_no) 
		where m.user_no = #{userNo}
	</select>
	
	<update id="modify" parameterType="crudMember">
		update member 
		set 
			user_name = #{userName},
			upd_date = sysdate 
		where user_no = #{userNo}
	</update>
	
	<delete id="deleteAuth" parameterType="int">
		delete from member_auth 
		where user_no = #{userNo}
	</delete>
	
</mapper>



package kr.or.ddit.controller.crud;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/crud/member")
public class CrudMemberController {

	@Inject
	private IMemberService service;
	
	@RequestMapping(value = "/register", method = RequestMethod.GET)
	public String crudMemberRegisterForm() {
		log.info("crudMemberRegisterForm() 실행...!");
		return "/crud/member/register";
	}
	
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public String crudMemberRegister(CrudMember member, Model model) {
		log.info("crudMemberRegister() 실행...!");
		service.register(member);
		model.addAttribute("msg", "등록이 완료되었습니다.");
		return "/crud/member/success";
	}
	
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String crudMemberList(Model model) {
		log.info("crudMemberList() 실행...!");
		List<CrudMember> memberList = service.list();
		model.addAttribute("memberList", memberList);
		return "/crud/member/list";
	}
	
	@RequestMapping(value = "/read", method = RequestMethod.GET)
	public String crudMemberRead(int userNo, Model model) {
		log.info("crudMemberRead() 실행...!");
		CrudMember member = service.read(userNo);
		model.addAttribute("member", member);
		return "/crud/member/read";
	}
	
	@RequestMapping(value = "/modify", method = RequestMethod.GET)
	public String crudMemberModifyForm(int userNo, Model model) {
		log.info("crudMemberModifyForm() 실행...!");
		CrudMember member = service.read(userNo);
		model.addAttribute("member", member);
		return "/crud/member/modify";
	}
	
	@RequestMapping(value = "/modify", method = RequestMethod.POST)
	public String crudMemberModify(CrudMember member, Model model) {
		log.info("crudMemberModify() 실행...!");
		service.modify(member);
		model.addAttribute("msg", "수정이 완료되었습니다.");
		return "/crud/member/success";
	}
	
	@RequestMapping(value = "/remove", method = RequestMethod.POST)
	public String crudMemberRemove(int userNo, Model model) {
		log.info("crudMemberRemove() 실행...!");
		service.remove(userNo);
		model.addAttribute("msg", "삭제가 완료되었습니다.");
		return "/crud/member/success";
	}
	
}
package kr.or.ddit.service;

import java.util.List;

import kr.or.ddit.vo.crud.CrudMember;

public interface IMemberService {

	public void register(CrudMember member);
	public List<CrudMember> list();
	public CrudMember read(int userNo);
	public void modify(CrudMember member);
	public void remove(int userNo);

}
package kr.or.ddit.service.impl;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.IMemberMapper;
import kr.or.ddit.service.IMemberService;
import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

@Service
public class MemberServiceImpl implements IMemberService {

	@Inject
	private IMemberMapper mapper;
	
	@Override
	public void register(CrudMember member) {
		// 회원 1명의 정보를 등록 시, 하나의 권한을 가질 수 있다.
		mapper.create(member); // 회원정보 1명의 데이터를 등록
		
		// 등록된 회원정보를 이용해서 권한을 등록
		CrudMemberAuth memberAuth = new CrudMemberAuth();
		memberAuth.setUserNo(member.getUserNo());
		memberAuth.setAuth("ROLE_USER");
		
		mapper.createAuth(memberAuth);
	}

	@Override
	public List<CrudMember> list() {
		return mapper.list();
	}

	@Override
	public CrudMember read(int userNo) {
		return mapper.read(userNo);
	}

	@Override
	public void modify(CrudMember member) {
		// 1) 일반 회원에 대한 데이터를 수정
		mapper.modify(member);
		// 2) 권한을 수정
		//		-> 회원번호에 대한 권한 모두를 삭제
		int userNo = member.getUserNo();
		mapper.deleteAuth(userNo);
		//		-> 새롭게 수정될 권한들을 insert
		List<CrudMemberAuth> authList = member.getAuthList();
		for(int i = 0; i < authList.size(); i++) {
			CrudMemberAuth memberAuth = authList.get(i);
			String auth = memberAuth.getAuth();
			if(auth == null) {
				continue;
			}
			if(auth.trim().length() == 0) {
				continue;
			}
			memberAuth.setUserNo(userNo);
			mapper.createAuth(memberAuth);
		}
	}

	@Override
	public void remove(int userNo) {
		mapper.deleteAuth(userNo); 	// 권한을 삭제
		mapper.delete(userNo);		// 회원정보 삭제
	}

}
package kr.or.ddit.mapper;

import java.util.List;

import kr.or.ddit.vo.crud.CrudMember;
import kr.or.ddit.vo.crud.CrudMemberAuth;

public interface IMemberMapper {

	public void create(CrudMember member);
	public void createAuth(CrudMemberAuth memberAuth);
	public List<CrudMember> list();
	public CrudMember read(int userNo);
	public void modify(CrudMember member);
	public void deleteAuth(int userNo);
	public void delete(int userNo);

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.IMemberMapper">
	
	<resultMap type="crudMember" id="memberMap">
		<id property="userNo" column="user_no" />
		<result property="userNo" column="user_no" />
		<result property="userId" column="user_id" />
		<result property="userPw" column="user_pw" />
		<result property="userName" column="user_name" />
		<result property="regDate" column="reg_date" />
		<result property="updDate" column="upd_date" />
		<collection property="authList" resultMap="authMap" />
	</resultMap>
	
	<resultMap type="crudMemberAuth" id="authMap">
		<result property="userNo" column="user_no" />
		<result property="auth" column="auth" />
	</resultMap>
	
	<insert id="create" parameterType="crudMember" useGeneratedKeys="true">
		<selectKey keyProperty="userNo" resultType="int" order="BEFORE">
			select seq_member.nextval from dual
		</selectKey>
		insert into member (
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		) values (
			#{userNo}, #{userId}, #{userPw}, #{userName}, sysdate, sysdate
		)
	</insert>
	
	<insert id="createAuth" parameterType="crudMemberAuth">
		insert into member_auth (
			user_no, auth
		) values (
			#{userNo}, #{auth}
		)
	</insert>
	
	<select id="list" resultType="crudMember">
		select 
			user_no, user_id, user_pw, user_name, reg_date, upd_date
		from member 
		order by user_no desc
	</select>
	
	<select id="read" parameterType="int" resultMap="memberMap">
		select 
			m.user_no, user_id, user_pw, user_name, reg_date, upd_date, 
			auth 
		from member m left outer join member_auth ma on(m.user_no = ma.user_no) 
		where m.user_no = #{userNo}
	</select>
	
	<update id="modify" parameterType="crudMember">
		update member 
		set 
			user_name = #{userName},
			upd_date = sysdate 
		where user_no = #{userNo}
	</update>
	
	<delete id="deleteAuth" parameterType="int">
		delete from member_auth 
		where user_no = #{userNo}
	</delete>
	
	<delete id="delete" parameterType="int">
		delete from member 
		where user_no = #{userNo}
	</delete>
	
</mapper>

- 전체적인 CRUD 확인해 볼 것...


 

'대덕인재개발원_웹기반 애플리케이션' 카테고리의 다른 글

231130_SPRING 2 (7-1)  (1) 2023.11.30
231129_SPRING 2 (6-3)  (0) 2023.11.29
231129_SPRING 2 (6-1)  (0) 2023.11.29
231128_SPRING 2 (5-2)  (0) 2023.11.28
231128_SPRING 2 (5-1)  (0) 2023.11.28