복습

Maven

- Spring 프로젝트는 Maven 으로만 라이브러리 관리 가능

- Springboo 프로젝트는 Maven, Gradle 둘 다 사용 가능

 

Maven 파일 구조

- src/main/java 에 확장자가 Java 인 파일을 넣는다

- src/main/resource 는 MyBatis 의 환경 설정 파일, 기존에 DAO 에 있었던 SQL문을 따로 빼서 만든 xml 파일

- src/main/webapp 는 View 페이지가 들어감, index 파일도 아 폴더 내에 들어간다 , 기존의 WebContent 폴더 역할

- src/main/webapp/WEB-INF 안에 프로젝트 환경 설정 파일인 web.xml 이 들어감, 그리고 기존의 lib 폴더는 사라짐

- DAO 클래스는 존재하지만 DAO 클래스의 SQL문을 따로 빼서 따로 파일을 만드는데, 그걸 mapper 파일이라고 부른다

- pom.xml 이 Maven 의 환경 설정 파일, 여기에서 의존 라이브러리를 추가

 

pom.xml 환경 설정 파일

- 오라클 jdbc, mysql jdbc, cos, mybatis, jstl 등 많은 라이브러리를 다운 받았었다

 

local repository 위치

 

프로젝트 구분

- Maven 프로젝트는 m , Spring 프로젝트는 s 가 붙어있다

 

Maven 프로젝트 / Spring 프로젝트 주의

- Maven 프로젝트, Spring 프로젝트는 war 파일로 export / import 하면 Dynamic Web Project 로 풀리므로 주의

- Maven 프로젝트, Spring 프로젝트는 프로젝트를 통째로 복사 붙여넣기해서 export 해야한다

- 이클립스에서 Spring 프로젝트 만드려면 플러그인 추가 또는 STS 라는 툴을 다운받아 사용

- Spring 프로젝트는 Mavne 프로젝트와 달리 기본적인 라이브러리가 이미 pom.xml 에 다 들어가 있다

- 아파치 톰캣이 자동으로 추가되지 않는 경우가 만흥므로 직접 추가해 준다


MyBatis

데이터베이스 접속 방식

- DB 접속 방식 3번째인 ORM 프레임워크 중 MyBatis 사용할 것

 

ORM 프레임워크

- ORM 프레임워크에서 Object 는 DTO 객체를 의미, Mapping 은 연결을 의미

- 즉 DTO 클래스의 필드와 테이블 안의 컬럼을 매핑시키는 것, 매핑 처리를 위해선 두 이름을 일치시켜야함

- ORM 프레임워크를 사용시 코드가 간단해진다

- 전자정부 프레임 워크에서는 MyBatis 사용함

- MyBatis 로 Model 1 에서도 연동해보고, Model 2 에서도 연동해 볼 것

 

프로젝트에 MyBatis 연동하기 위해 필요한 파일

- MyBatis 와 연동하기 위해서는 크게 2가지 파일이 필요하다

1. MyBatis 의 환경설정 파일

2. 기존 DAO 파일에 들어있던 내용인 Mapper 파일

- 이 2개 파일이 src/main/resources 폴더 안에 있어야 한다 

 

프로젝트에 MyBatis 연동하는 방법

1. MarketPlace 에서 MyBatis Plugin 프로그램을 설치해야한다

- Mapper 파일을 생성할 수 있는 메뉴가 추가됨

- 과거에는 MarketPlace 에서 플러그인 설치시 MaBatis 환경설정 파일도 만들 수 있었지만 현재는 불가능

- 그리고 이클립스를 재시작한다

 

2. Mapper 파일을 생성해야 한다

- maventest 프로젝트의 resources 폴더에서 오른쪽 마우스 클릭

- 플러그인인을 설치시 Mapper 파일을 생성할 수 있는 메뉴가 나타남

- resources 폴더 안에 Mapper 파일이 들어갔다

- mapper.xml (예시)

- 이 파일 안에 DAO 의 insert, update, delete, select 가 들어감

- xml 파일이므로 루트 엘리먼트가 있어야하고, 루트 엘리먼트가 mapper

- insert 태그 사이에 insert SQL문 작성, 다른 DML 문도 마찬가지, 태그에는 각 SQL문을 구분하기 위한 id 가 있다

 

3. 다음으로는 MyBatis 환경설정 파일이 다운받아진 프로젝트를 import 해서 MaBatis 환경설정 파일을 살펴보자

- 현재는 플러그인 추가해도 MaBatis 환경설정 파일 생성 불가

 

MaBatis 프로젝트 import 하기

- mybatistest 프로젝트 import

- mabatistest.zip 파일을 다운로드 받아서 압축 해제 후 import

- mybatistest 가 import 되었다

- MyBatis 와 연동되는 이 3개 파일들은 모두 src/main/resources 폴더 안에 저장되어 있어야 함

 

MyBatis 연동 관련 파일 살펴보기

1. db.properties

#mysql
#jdbc.driverClassName=com.mysql.jdbc.Driver
#jdbc.url=jdbc:mysql://localhost:3306/jsptest
#jdbc.username=jspid
#jdbc.password=jsppass

#oracle
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.username=scott
jdbc.password=tiger

- DB 접속에 필요한 내용들이 들어간다

- 위에는 mysql 과 연동하는 내용, 아래는 oracle 과 연동하는 내용을 작성했다

- 왼쪽은 변수명, 오른쪽은 변수에 할당될 값이다

- jdbc.driverClassName 변수명은 정해져 있는 이름이다, 경로를 oracle.jdbc.driver.OracleDriver 로 설정

- jdbc.url 변수에는 jdbc:oracle:thin:@localhost:1521:xe 로 DB 경로를 설정

- 현재는 scott 계정으로 연결 설정했다

- # 은 주석

- mybatis-config.xml 파일에서 이 파일 db.properties를 불러온다

 

2. mybatis-config.xml

- MyBatis 의 환경설정 파일이다

+ 환경 설정 파일은 대부분 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>
	<properties resource="db.properties" />
	<typeAliases>
		<typeAlias type="#package.#modelname" alias="#modelname"></typeAlias>
	</typeAliases>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driverClassName}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="#package/#mapper.xml" />
	</mappers>
</configuration>

- 위의 DOCTYPE configuration 내용을 삭제하면 안된다, mybatis.org/dtd/mabatis-3-config.dtd 문서를 불러오고 있다

- 루트 엘리먼트는 configuration

 

Mabatis 환경설정 파일인 mybatis-config.xml 파일 안에 들어가는 내용 3가지

0) properties 태그에서 db.properties 파일을 불러온다

1) typeAliases 태그로 DTO 클래스의 경로를 alias 로 간단한 별칭을 설정

- typeAlias 태그의 type 속성에서 DTO 클래스의 경로를 패키지부터 해당 클래스까지의 경로로 작성

- typeAlias 태그의 alias 속성에서 alias는 별칭을 의미, 그 경로를 짧은 별칭으로 설정하는 것

- DTO 클래스가 많아지면 typealias 태그를 추가해주면 된다

2) environments 태그 안의 property 태그에서 DB 접속 관련 내용들 작성

- property 태그는 클래스의 멤버변수(필드, 프로퍼티) 를 의미, name 속성값은 고정되어있고, values 값으로 db.property 안의 변수명을 이용해서 변수값을 불러오고 있다

+ 변수명으로 불러오는 대신 그 자리에 바로 값을 써도 된다

ex) <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>

- 그렇게 드라이브의 경로, DB 경로, 계정명, 비밀번호 등을 불러옴

- db 접속하는 내용들이 들어간다

- 위에서 db.property 파일을 불러왔으므로 가능함

3) mappers 태그 안의 mapper 태그로 SQL문이 들어간 파일인 Mapper 파일을 불러오기

- mapper 태그의 resource 속성에 패키지명을 적어주고, Mapper 파일명을 써주기

+ 여기서 mapper 태그 안에서 Mapper 파일을 불러오므로 Mapper 파일의 루트 엘리먼트도 mapper 이다

- Mapper 파일은 테이블의 개수에 비례해서 늘어난다

- Mapper 파일이 늘어나면 mapper 태그를 추가해주면 된다

 

3. mapper.xml

- Mapper 파일 이다

- 이름은 반드시 mapper.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="#package.#mapperinterfacename">

	<select id="getSomething" parameterType="int" resultType="#package.#modelname">
		SELECT
		columnname1,
		columnname2,
		columnname3
		FROM tablename1
		WHERE columnname1 = #{value}
	</select>

	<resultMap type="#modelname" id="YourResultSet">
		<id property="param1" column="columnname1" />
		<result property="param2" column="columnname2" />
		<result property="param3" column="columnname3" />
	</resultMap>

	<select id="getAll" resultMap="YourResultSet">
		SELECT * FROM tablename1
	</select>

	<insert id="insertSomething" parameterType="#modelname">
		INSERT INTO tablename1 (columnname1, columnname2, columnname3)
		VALUES(#{value1},#{value2},#{value3})
	</insert>

	<update id="updateSomething" parameterType="#modelname">
		UPDATE tablename1
		SET
		columnname1=#{param1}
		WHERE
		columnname2 = #{param2}
	</update>

	<delete id="deleteSomething" parameterType="int">
		DELETE FROM tablename1 WHERE
		columnname1 = #{param1}
	</delete>

</mapper>

- select 문은 select 태그로 감싸준다

- 태그들을 구분하기 위해 id 값을 다르게 설정한다

- DAO 파일에서 이 Mapper 파일의 id 값을 불러서 사용한다

<값 전달하기 : parameterType>

- insert , select 할 데이터는 parameterType 속성으로 값을 받는다

- parameterType 속성값에 전달되는 값의 자료형을 작성

< 검색한 값 돌려받기 : returnType >
- select 해서 검색한 결과를 resultType 속성으로 값을 돌려준다

- select SQL문만 returnType 속성을 사용함

- resultType 속성값에는 값을 돌려줄때의 자료형을 작성

- #{} 에서 getter 메소드로 불러올 값들을 작성함

< 검색한 값 돌려받기 : 데이터 1개 검색 >

- 데이터를 1개 검색했을때는 if(rs.next()) 로 가져와서 DTO 객체에 저장했었다, 일일히 setter 메소드로 저장했었음

- 이제는 일일히 setter 메소드를 작성하지 않고 컬럼명에 일치하는 DTO 프로퍼티가 있을땐 자동으로 setter 메소드를 불러서 매핑해준다

- returnType 에 DTO 경로 별칭만 써주면 테이블명과 DTO 프로퍼티가 일치하는 경우에 자동으로 매핑

< 검색한 값 돌려받기 : 데이터 2개 이상 검색 >

- 2개 이상의 데이터를 검색할때는 리스트를 통해 값을 받았었다, 여기서는 resultType 으로 DTO 클래스의 alias 명을 쓰면 된다, 리스트에 저장시키는 것 까지 자동으로 해줌

- returnType 에 DTO 경로 별칭만 써주면 테이블명과 DTO 프로퍼티가 일치하는 경우에 자동으로 매핑, 리스트 저장까지 해줌

<자료형이 DTO일땐>

- 전달되는 값의 자료형이나 돌려주는 값의 자료형이 DTO일땐, MyBatis 환경설정 파일에서 설정한 DTO 클래스의 alias 값이 파라미터 타입값으로 들어가야한다

<resultMap>

- resultMap 은 컬럼명과 DTO 프로퍼티명이 일치하지 않을때, resultMap 으로 일일히 매핑을 잡아줘야한다

- resultMap 태그 안에서 컬럼과 프로퍼티를 일일히 매핑


JSP - MyBatis 연동

Model 1 과 MyBatis 연동

- 클라우드에서 Model 1 과 MyBatis 가 이미 연동이 완료된 member22 프로젝트 import

- zip 파일을 압축 풀어서 import

+ 그냥 member22 파일을 바로 import 하면 . 으로 시작된 파일들이 import 안된다

+ 반드시 zip 파일을 풀어서 생성된 폴더를 import 하기

- src/main/java 안에 확장자가 java 인 파일들이 저장되어있다

- src/main/resources 안에 DB 연동에 필요한 MyBatis 환경설정 파일 등이 들어가 있다

- src/main/webapp 안에 View 파일 등이 들어간다

 

- import한 member22 프로젝트의 pom.xml 파일을 보자

- pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.myhome</groupId>
	<artifactId>member22</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>member22 Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<!-- 오라클 repository -->
	<repositories>
		<repository>
			<id>codelds</id>
			<url>https://code.lds.org/nexus/content/groups/main-repo</url>
		</repository>
	</repositories>

	<dependencies>

		<!-- 오라클 JDBC Library -->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0.3</version>
		</dependency>

		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.47</version>
		</dependency>

		<!-- iBatis -->
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-sqlmap</artifactId>
			<version>2.3.4.726</version>
		</dependency>

		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.3</version>
		</dependency>

		<!-- jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.taglibs</groupId>
			<artifactId>taglibs-standard-impl</artifactId>
			<version>1.2.5</version>
		</dependency>

		<!-- cos -->
		<dependency>
			<groupId>servlets.com</groupId>
			<artifactId>cos</artifactId>
			<version>05Nov2002</version>
		</dependency>
		
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>member22</finalName>
	</build>
</project>

- dependencies 태그 안에 의존 라이브러리를 dependency 태그로 추가

- 오라클 JDBC, MySQL JDBC, iBatis, MyBatis 3.5.3 ver, JSTL, cos 라이브러리가 추가되었다

- 오라클 공식 저장소에서 다운받는 건 오류 많이 발생

- 오라클은 비공식 저장소 repository 를 원격 저장소 위치로 등록하고 거기서 오라클 JDBC 라이브러리를 불러오기

- MyBatis 연동시에는 반드시 MyBatis 라이브러리가 추가되어 있어야함

 

Model 1 에 MyBatis 연동시 구조

- Model 1 에서 MyBatis 를 연동하면 DAO 이후부터만 달라진다

- 앞부분은 Model 1과 동일하고 달라지는 내용은 DAO 이후 부터 이다

- DAO 메소드 안의 복잡한 내용들이 빠져서 MyBatis 환경설정 파일로 간다

- 안의 SQL문들이 빠져서 Mapper 파일인 member.xml 으로 간다

 

- 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>
	<properties resource="db.properties" />
	<typeAliases>
		<typeAlias type="model.Member" alias="member"></typeAlias>
	</typeAliases>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driverClassName}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="member.xml" />
	</mappers>
</configuration>

- model 패키지 안의 DTO 경로를 alias 속성을 통해 member 라는 별칭으로 지정

- mapper 태그로 Mapper 파일인 member.xml 파일을 불러옴, 같은 폴더 안에 있으므로 이름만으로 불러옴

- Mapper 파일이 다른 패키지안에 있으면 불러올 때 패키지명도 명시해줘야함

 

- Mapper 파일인 member.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="memberns">

	<insert id="insert" parameterType="member">
		insert into member22 values (#{id}, #{password})
	</insert>
	
	<select id="list" resultType="member">
		select * from member22
	</select>
	
	<select id="select" parameterType="String" resultType="member">
		select * from member22 where id = #{id}
	</select>	
	
	<update id="update" parameterType="member">
		update member22 set password = #{password} where id = #{id}
	</update>
	
	<delete id="delete" parameterType="String">
		delete from member22 where id = #{id}
	</delete>
	
</mapper>

 

- db.properties

#mysql
#jdbc.driverClassName=com.mysql.jdbc.Driver
#jdbc.url=jdbc:mysql://localhost:3306/jsptest
#jdbc.username=jspid
#jdbc.password=jsppass

#oracle
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.username=totoro
jdbc.password=totoro123

 

- db.properties 파일에서 totoro 계정으로 설정되어있으므로 totoro 계정에서 테이블을 생성해야함

+ import 시에 테이블이 생성되지는 않음

- sql 폴더의 member.sql 에서 totoro 계정으로 연결한 후 member22 테이블을 생성하자

- member.sql

-- model1 과 mybatis 연동
select * from tab;
select * from member22;

create table member22 (
	id varchar2(10) primary key,
	password varchar2(10)
);

- 테이블 member22 를 생성하자

- 테이블의 필드명과 DTO 클래스의 멤버변수(필드, 프로퍼티) 명을 같은 이름으로 설정해야한다

+ 간소화 시킨 테이블임


흐름 설명

- src/main/java 에서 model 패키지의 DTO 클래스인 Member.java 를 보자

package model;

public class Member {
	private String id;
	private String password;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
}

- 프로퍼티명이 컬럼명과 동일하게 id, password 로 되어있다, 쉽게 매핑 가능해짐

 

- 회원가입 페이지인 joinForm.jsp 에서 form 의 name 값도 똑같이 id, password 로 일치시킨다

- 그렇게 해야 setProperty 로 쉽게 저장 가능 (Model 1)

- joinForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>

<body>
<h2>회원가입</h2>
<form action="joinPro.jsp">
	아이디 : <input type="text" name="id" required="required"><p>
	암호 : <input type="password" name="password" required="required"><p>
	<input type="submit" value="확인">
</form>
</body>
</html>

 

- loginForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>

<body>
<h2>로그인</h2>
<form action="loginPro.jsp" >
	아이디 : <input type="text" name="id" required="required"><p>
	암호 : <input type="password" name="password" required="required"><p>
	<input type="submit" value="확인">
</form>
<p><a href="joinForm.jsp">회원가입</a>
</body>

</html>

 

- index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<html>
<body>
<h2>Hello World!</h2>

<script>
	location.href="member/loginForm.jsp";
</script>

</body>
</html>

- index 파일은 webapp 폴더 안에 저장되어 있어야함

- index 파일을 실행시켜도 되고, 현재 프로젝트 선택 후 Run As - Run on Server 로 실행 하면 index 파일이 실행됨

- 실행시 index.jsp 파일에서 loginForm.jsp 파일을 실행시킴

- 회원 가입을 해보자, 클릭 시 joinForm.jsp 파일로 넘어감

- '확인' 시 joinPro.jsp 파일로 넘어가면서 id, password 를 네임값으로 해서 입력된 값을 전달

- joinPro.jsp 에서 setProperty 로 DTO 객체 mem에 값 설정 후 insert(mem) 호출

- 가입 후 로그인

- master 란 아이디로 가입시 관리자

- 관리자로 로그인 시 나오는 내용이 달라짐

- 회원명단을 볼 수 있는 메뉴가 나타남

- 즉, 관리자로 로그인 시 나오는 내용이 달라짐

- 회원 수정이나 회원 탈퇴 시킬 수 있다

 

- 앞부분은 Model 1과 동일하고 달라지는 내용은 DAO 이후 부터 이다

- DAO 클래스가 SQL문을 실행하는 것은 같지만, DAO 클래스 안에서 SQL문이 빠져서 Mapper 파일로 간다

 

- Mapper 파일인 member.xml 파일을 보자

-member.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="memberns">

	<insert id="insert" parameterType="member">
		insert into member22 values (#{id}, #{password})
	</insert>
	
	<select id="list" resultType="member">
		select * from member22
	</select>
	
	<select id="select" parameterType="String" resultType="member">
		select * from member22 where id = #{id}
	</select>	
	
	<update id="update" parameterType="member">
		update member22 set password = #{password} where id = #{id}
	</update>
	
	<delete id="delete" parameterType="String">
		delete from member22 where id = #{id}
	</delete>
	
</mapper>

- id 값은 태그를 구별하는 역할, 이 파일 내에선 중복되선 안되는 값이다

- update 문은 update 태그 안에 작성

- DAO 클래스에서 이 id 값을 불러온다, 즉, 안의 SQL문을 불러온다

- 전달되는 값의 자료형을 parameterType 에 쓰고 돌려주는 값의 자료형을 resultType 에 쓴다

- resultType 은 select 태그 (select 문) 에만 사용가능하다

- 전달되는 값이 없을땐 parameterType 속성을 사용하지 않음

- DTO 객체가 전달되는 값의 자료형이거나 돌려주는 값의 자료형일땐 alias (별칭) 값을 쓴다

- 2개 이상의 데이터를 검색할때도 똑같이 DTO 객체인 alias 값을 사용하면 자동으로 리스트에 저장해서 돌려줌

 

- 다음은 MyBatis 환경 설정 파일인 mybatis-config.xml 을 보자

- 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>
	<properties resource="db.properties" />
	<typeAliases>
		<typeAlias type="model.Member" alias="member"></typeAlias>
	</typeAliases>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driverClassName}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="member.xml" />
	</mappers>
</configuration>

1. 이 alias 를 Mapper 파일안에서 값을 받고 돌려줄때 사용한다

+ alias 를 설정하지 않았다면 패키지부터 클래스까지 전부 써야한다

2. DB 접속에 필요한 내용을 property 태그 안에 작성, db.properties 파일의 변수를 불러와서 설정

+ 변수 불러오지 않아도 바로 적어도 된다

3. Mapper 파일을 불러오고 있다

 

DAO 클래스에서 id 값을 불러오는 원리

- DAO 에서 바로 Mapper 파일의 id를 불러올 수 없다

- 먼저 MyBatis 환경설정 파일 3번째 자리에서 Mapper 파일을 불러온다

- DAO에서는 MyBatis 환경 설정 파일을 불러옴으로서 id 를 불러올 수 있음

- 즉 Mapper 파일을 MyBatis 환경설정 파일에서 불러오고, MyBatis 환경설정 파일을 DAO 에서 불러온다

- 연쇄적으로 불러오기 때문에 Mapper 파일에 설정된 id 를 DAO 클래스에서 불러 올 수 있음

 

- DAO 클래스인 MemberDao.java 를 보자

- MemberDao.java

package dao;

import java.io.IOException;
import java.io.Reader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import model.Member;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MemberDao {
	
	private SqlSession getSession() {
		SqlSession session=null;
		Reader reader=null;
		try {
			reader = Resources.getResourceAsReader("mybatis-config.xml");
			SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(reader);
			session = sf.openSession(true);			// auto commit
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
		return session;
	}

	public int insert(Member member) {
		int result = 0;
		SqlSession session=null;
		try { 
			session = getSession(); 
			result = session.insert("insert", member);			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

	public int chk(Member member) {
		int result = 0;
		SqlSession session=null;
		try { session = getSession(); 
			Member mem = (Member) session.selectOne("select", member.getId());
			if (mem.getId().equals(member.getId())) {
				result = -1;
				if (mem.getPassword().equals(member.getPassword())) {
					result = 1;
				}
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

	public Member select(String id) throws SQLException {
		Member mem = null;
		SqlSession session=null;
		try { session = getSession(); 
		mem = (Member) session.selectOne("select", id);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return mem;
	}

	public List<Member> list() {
		List<Member> list = new ArrayList<Member>();
		SqlSession session=null;
		try { session = getSession(); 
			list = session.selectList("list");
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return list;
	}

	public int delete(String id) {
		int result = 0;
		SqlSession session=null;
		try { session = getSession(); 
			result = session.delete("delete", id);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

	public int update(Member mem) {
		int result = 0;
		SqlSession session=null;
		try { session = getSession(); 
			result = session.update("update", mem);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}
}

- 마찬가지로 DB 연동을 처리하는 클래스이다

- SQL문이 빠지고 Mapper 파일인 member.xml 파일에 들어가있다

- SQL문을 제외한 나머지 내용이 들어가있음, 메소드만으로 구성되어있다

+ MyBatis 지원 클래스/인터페이스 (SqlSession 인터페이스 등) 들을 import 하고 있다 * 아래에 설명

 

SqlSession 객체 구하기 / MyBatis 환경설정 파일 읽어오기 (MemberDao.java 부분 getSession() 메소드)

	private SqlSession getSession() {
		SqlSession session=null;
		Reader reader=null;
		try {
			reader = Resources.getResourceAsReader("mybatis-config.xml");
			SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(reader);
			session = sf.openSession(true);			// auto commit
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
		return session;
	}

- getSession() 메소드에서는 try 안의 3줄을 통해 SqlSession 객체를 구해준다, 그 객체를 통해 SQL문을 실행하는 메소드들을 사용 가능하다

- Reader 객체를 구할때 MyBatis 환경설정 파일인 mybatis-config,xml 을 불러오고 있다, MyBatis 환경설정 파일에서는 Mapper 파일을 불러옴

- 그렇기 때문에 DAO 에서 Mapper 파일의 id 값을 불러올 수 있다, 즉 Mapper 파일의 SQL문을 불러올 수 있음

- sf.openSession(true) 를 하면 자동 커밋이 된다, 자동 커밋이 되지 않는다면 SQL문을 수행 후 일일히 session.commit() 으로 커밋을 수행해야함

* 커밋을 해야 DB에 실제 삽입, 수정, 삭제 등이 됨

 

DAO 안에서 id 로 불러와서 SQL문 실행 (MemberDao.java 부분)

	public int insert(Member member) {
		int result = 0;
		SqlSession session=null;
		try { 
			session = getSession(); 
			result = session.insert("insert", member);			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

- 가장 먼저 getSession() 메소드로 SqlSession 객체를 구한다

- DAO 안의 메소드 안에서 그 SQL문을 실행해야하는데, 이때 SqlSession 에서 지원하는 메소드를 사용한다

- insert() 메소드를 사용해서 id 값인 "insert" 로 Mapper 클래스의 insert 문을 불러온다

메소드에서 메소드 첫번째 매개변수에는 id값, 전달될 값이 있다면 두번째 매개변수에 전달될 값을 전달

- 여기서는 전달받은 DTO 객체인 member 를 두번째 매개변수를 통해 전달하고 있음

- insert() 메소드를 실행 후 삽입 성공한 데이터 개수를 자동으로 반환해줌

- 위의 insert() 메소드는 SQL문을 실행시켜주는 메소드 5가지 중 하나이다

 

SQL문을 실행시켜주는 메소드 5가지 (MemberDao.java 부분)

- SQL문에 따라서 메소드가 정해져 있다

- 이 메소드를 지원하는 인터페이스 SqlSession 객체를 구해와야만 이 메소드 5개를 사용 가능하다

- 그래서 위에서 getSession() 메소드로 SqlSession 객체를 구해왔다

+ SqlSession 은 MyBatis 에서 지원되는 인터페이스

 

- insert SQL문은 insert() 메소드로 실행해야한다, update, delete 도 마찬가지

- 검색되는 결과가 1개인 select 문은 selectOne() 메소드로 실행

- 결과를 Object 형으로 돌려준다, 다운캐스팅

+ Member 는 DTO 클래스 이름이다

- 검색되는 결과가 2개 이상인 selec 문은 selectList() 메소드로 실행

- 결과를 List 로 돌려준다

 

- insert() / update() / delete() 메소드는 삽입, 수정, 삭제된 데이터 개수를 자동으로 돌려준다

- 메소드 자체적으로 값을 자동으로 돌려주므로 Mapper 파일에서 insert / update / delete 문은 resultType 을 쓰면 안됨

- resultType 은 select 문만 사용가능

<데이터를 1개 검색시>

- selectOne() 메소드를 사용시에는 값을 Object 형 으로 돌려주므로 다운캐스팅 해야한다

- resultType 에는 DTO 객체를 쓴다

<데이터를 2개 이상 검색시>

- 데이터 2개 이상 검색하는 select문에서도 resultType 에는 DTO 객체만 쓴다, List 를 쓰지 않음! 자동으로 리스트를 잡아서 돌려준다

- 일일히 가져와서 DTO 객체 에 setter 메소드로 저장했었지만 이제는 검색된 데이터의 컬럼명과 DTO 프로퍼티명이 같다면 자동으로 순차적으로 DTO 객체에 저장하면서 List 를 만들어서 돌려줌

 

Mapper 의 insert SQL문을 insert() 메소드로 불러와서 실행 (MemberDao.java 부분, 중복) 

- update(), delete() 도 마찬가지

	public int insert(Member member) {
		int result = 0;
		SqlSession session=null;
		try { 
			session = getSession(); 
			result = session.insert("insert", member);			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

- SqlSession 객체가 있어야 insert() 메소드 사용 가능, 이전에 정의한 getSession() 으로 객체를 받아온다

- insert() 메소드 자체적으로 삽입에 성공한 데이터 개수를 돌려주는 기능이 있으므로 Mapper 파일의 insert에 resultType 을 써선 안됨

- 그렇게 돌려받은 값을 result 변수에 받아서 그 변수를 리턴하고 있음

- insert() 메소드에서 메소드 첫번째 매개변수에는 id값, 전달될 값이 있다면 두번째 매개변수에 전달될 값을 전달

- 여기서는 전달받은 DTO 객체인 member 를 두번째 매개변수를 통해 전달하고 있음

- Mapper 파일의 parameterType 에서도 같은 자료형인 DTO 를 써야함

- Mapper 파일 member.xml 부분

	<insert id="insert" parameterType="member">
		insert into member22 values (#{id}, #{password})
	</insert>

- parameterType 에는 전달될 값의 자료형을 적음, DTO 객체를 전달받아야하므로 alias 로 설정한 별칭인 member 를 적는다

- #{} 안에 DTO 클래스의 필드명을 써서, 값을 가져온다.

- 표기만 이럴뿐 DTO 객체에 직접 접근하는 것이 아니라 getter 메소드로 가져오는 것임

- #{id} 의 의미는 member.getId() 로 리턴받은 값을 의미함

- #{password} 의 의미는 member.getPassword() 로 리턴받은 값을 의미

 

+ 단점 : 값을 1개만 전달 가능

 

Mapper 의 select SQL문을 select() 메소드로 불러와서 실행 1(MemberDao.java 부분)

	public Member select(String id) throws SQLException {
		Member mem = null;
		SqlSession session=null;
		try { session = getSession(); 
		mem = (Member) session.selectOne("select", id);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return mem;
	}

- SqlSession 객체가 있어야 select() 메소드 사용 가능, 이전에 정의한 getSession() 으로 객체를 받아온다

- select() 메소드는 돌려주는 데이터가 몇개인지에 따라 다른 메소드를 쓴다, 1개 데이터를 돌려줄때는 selectOne() 사용

- 두번째 매개변수로 사용자의 id 값을 전달

- 마찬가지로 Mapper 파일의 parameterType 도 String 형으로 설정해야함

- Mapper 파일 member.xml 부분

	<select id="select" parameterType="String" resultType="member">
		select * from member22 where id = #{id}
	</select>

- 넘어오는 값은 사용자의 id 값이므로 paramterType 은 String 으로 설정해야함

- #{id} 의 의미는 전달된 변수 id 값을 가져오는 것임

- 데이터 1개를 돌려주므로 resultType 을 DTO 의 alias 인 member 로 설정

- if(rs.next()) 안에서 수행했던 member.setId(rs.getString("id")) 를 더이상 쓰지 않음, 돌려주는 객체 member 에 자동으로 setter 메소드로 값을 다 저장해서 돌려준다

+ DTO 프로퍼티명과 컬럼명이 일치하는 경우에만 가능

 

Mapper 의 select SQL문을 select() 메소드로 불러와서 실행 2(MemberDao.java 부분)

- 위의 select() 와는 다른 메소드, 이건 로그인 시 회원 인증을 해주는 chk() 메소드이다

	public int chk(Member member) {
		int result = 0;
		SqlSession session=null;
		try { session = getSession(); 
			Member mem = (Member) session.selectOne("select", member.getId());
			if (mem.getId().equals(member.getId())) {
				result = -1;
				if (mem.getPassword().equals(member.getPassword())) {
					result = 1; // 회원인증 성공
				}
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

- 로그인 시 회원인증을 처리하는 부분이다

- mem.getId() 는 DB에 저장된 id 를 의미하고, member.getId()는 사용자가 입력한 id 를 의미

- mem.getPassword() 는 DB에 저장된 password 를 의미하고, member.getPassword()는 사용자가 입력한 password 를 의미

- id, password 가 모두 일치할때는 변수 result 에 1 을 저장해서 리턴함, 이 값으로 로그인 성공을 판별하는 것은 loginPro.jsp 에서 처리함

- id 는 일치하되, passoword 가 일치하지 않을때는 변수 result 에 -1 을 저장해서 리턴, 이것도 loginPro.jsp 에서 처리

 

- Mapper 파일 member.xml 부분

	<select id="select" parameterType="String" resultType="member">
		select * from member22 where id = #{id}
	</select>

회원가입 기능

Model 1 & MyBatis 회원 가입 흐름

1. 처음 index.jsp 실행 -> loginForm.jsp -> '회원가입' 눌러서 joinForm.jsp 로 넘어감

2. joinForm.jsp 에서 입력된 값을 id, password 네임값에 저장해서 joinPro.jsp 로 전달

3. joinPro.jsp 에서 useBean 과 setProperty 로 DTO 객체 mem 생성 후 값 저장, DAO 객체의 insert(mem) 호출함

4. DAO 에서 insert() 메소드를 실행, 그 안에서 Mapper 파일의 insert SQL문을 id 로 불러온다

- insert() 가 잘 수행되면 1을 돌려줌

5. joinPro.jsp 로 돌아오고, 회원가입 성공 시 loginForm.jsp 로 넘어간다, 실패(중복아이디)시 이전페이지로 이동

 

- joinForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>

<body>
<h2>회원가입</h2>
<form action="joinPro.jsp">
	아이디 : <input type="text" name="id" required="required"><p>
	암호 : <input type="password" name="password" required="required"><p>
	<input type="submit" value="확인">
</form>
</body>
</html>

 

- joinPro.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="dao.*"%>

<jsp:useBean id="mem" class="model.Member"/>
<jsp:setProperty property="*" name="mem"/>

<%
MemberDao md = new MemberDao();
int result = md.insert(mem);

if (result>0) {
%> 
	<script type="text/javascript">
		alert("가입성공");
		location.href="loginForm.jsp";
	</script>
<%
} else {
%> 
	<script type="text/javascript">
		alert("가입 실패");
		history.go(-1);
	</script>
<%
}
%>

 

- MemberDao.java 에서 insert() 메소드 부분만

	public int insert(Member member) {
		int result = 0;
		SqlSession session=null;
		try { 
			session = getSession(); 
			result = session.insert("insert", member);			
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

 


- member.xml 에서 회원 가입을 처리하는 SQL문 부분 (id 가 insert)

	<insert id="insert" parameterType="member">
		insert into member22 values (#{id}, #{password})
	</insert>

로그인 기능

Model 1 & MyBatis 로그인 흐름

1. 처음 index.jsp 실행 -> loginForm.jsp 로 넘어감

2. loginForm.jsp 에서 입력된 값을 id, password 네임값에 저장해서 loginPro.jsp 로 전달

3. loginPro.jsp 에서 useBean 과 setProperty 로 DTO 객체 mem 생성 후 값 저장, DAO 객체의 chk(mem) 호출함

4. DAO 에서 chk() 메소드를 실행, 그 안에서 Mapper 파일의 select SQL문을 id 로 불러온다, selectOne() 가 잘 수행되면 DB에 저장된 사용자의 정보를 가져옴

- 다운캐스팅 해서 DTO 객체에 저장 (다운캐스팅 생략해도 작동한다)

- 그 정보가 사용자가 입력한 값과 일치시 result 에 1을 저장해서 돌려준다

5. loginPro.jsp 로 돌아오고 회원 인증 성공 시 id 를 세션 공유 설정하고 main.jsp 로 넘어간다, 실패(중복아이디)시 이전페이지로 이동

 

- loginForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>

<body>
<h2>로그인</h2>
<form action="loginPro.jsp" >
	아이디 : <input type="text" name="id" required="required"><p>
	암호 : <input type="password" name="password" required="required"><p>
	<input type="submit" value="확인">
</form>
<p><a href="joinForm.jsp">회원가입</a>
</body>

</html>

 

- loginPro.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="dao.MemberDao"%>

<jsp:useBean id="mem" class="model.Member"/>
<jsp:setProperty property="*" name="mem"/>

<%
MemberDao md = new MemberDao();
int result = md.chk(mem);

if (result==1) {
	session.setAttribute("id",mem.getId());
%> 
	<script type="text/javascript">
		alert("환영함");
		location.href="main.jsp";
	</script>
<%
} else if (result == -1) {
%> 
	<script type="text/javascript">
		alert("비번이 다르다");
		history.go(-1);
	</script>
<%
} else {
%> 
	<script type="text/javascript">
		alert("그런 ID가 없습니다.");
		history.go(-1);
	</script>
<%
}
%>

 

- MemberDao.java 에서 chk() 메소드 부분만

	public int chk(Member member) {
		int result = 0;
		SqlSession session=null;
		try { session = getSession(); 
			Member mem = (Member) session.selectOne("select", member.getId());
			if (mem.getId().equals(member.getId())) {
				result = -1;
				if (mem.getPassword().equals(member.getPassword())) {
					result = 1; // 회원인증 성공
				}
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

 

- member.xml 에서 로그인(회원 인증)을 처리하는 SQL문 부분 (id 가 select)

	<select id="select" parameterType="String" resultType="member">
		select * from member22 where id = #{id}
	</select>

 


DAO 클래스 상단에서 MyBatis 지원 클래스 / 인터페이스 import



중간 페이지 기능

- 로그인 성공시 이동하는 main.jsp 내용을 보자

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>

<%
 	String id = (String) session.getAttribute("id");
if (id == null || id.equals("")) {
	response.sendRedirect("loginForm.jsp");
} else if (id.equals("master")) {
	out.println("관리자 모드!");	
} 
%>

<body>
	로긴함
	<p>
		정보수정<br>
<%
		if (id != null) {
		if (id.equals("master")) {
%>
		<a href="list.jsp">회원명단</a><br>
<%
		}}
%>
		<a href="logout.jsp">로그아웃</a>
		
</body>
</html>

-로그인 성공시 공유한 공유값 id 값을 가져와서 사용

- getAttribute() 로 공유값을 가져올때는 다운캐스팅을 해야함

- 받아온 공유값인 id 가 null 인 경우, Redirect 포워딩 팡식으로 loginForm.jsp 로 넘어감

- 받아온 공유값인 id 가 "master" 인 경우 "관리자 모드!" 라는 메세지가 출력됨

<body 태그 안>

- 받아온 공유값인 id가 "master" 인 경우 "회원명단" 출력, 클릭시 list.jsp 로 이동하도록 설정

- 어느 아이디로 로그인되었느냐에 따라 main.jsp 내용이 달라짐

- '로그아웃' 클릭시 logout.jsp 로 이동 : 세션 삭제, 로그아웃 메세지 출력하고 로그인 폼으로 이동하는 작업을 한다


로그아웃 기능

- '로그아웃' 을 클릭시 넘어가는 logout.jsp 를 보자

- logout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
session.invalidate();
%>

<script type="text/javascript">
	alert("로그아웃 됨");
	location.href="loginForm.jsp";
</script>

</body>
</html>

1. 세션 삭제(끊어줌)

2. 로그아웃 메세지 출력하고 loginForm.jsp 로 이동

- 이 두가지 작업만 한다

- DB 연동 안함


목록 페이지 기능

- '회원명단' 을 클릭시 넘어가는 list.jsp 를 보자

- list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="java.util.List"%>
<%@page import="model.Member"%>
<%@page import="dao.MemberDao"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

회원 명단
<table border=1><tr><th>아이디</th><th>비밀번호</th><th>수정</th><th>삭제</th></tr>

<%
	MemberDao md = new MemberDao();
	List<Member> list = md.list();
	
for (int i = 0;i<list.size();i++){
%>
	<tr><td><%=list.get(i).getId() %></td><td><%=list.get(i).getPassword() %></td>
	<td><input type="button" value="수정" onclick='location.href="updateForm.jsp?id=<%=list.get(i).getId() %>"'></td>
	<td><input type="button" value="삭제" onclick='location.href="delete.jsp?id=<%=list.get(i).getId() %>"'></td></tr>
<%
}
%>
</table>

<a href="main.jsp">메인으로</a>

</body>
</html>

- id 가 master 인 관리자 계정만 볼 수 있다

- DB 연동을 수행해서 전체를 검색한다, DAO 객체 생성해서 전체 회원 목록을 구해오는 list() 메소드 호출

- 결과를 list 로 돌려받은 다음 반복문에서 get() 과 getter 메소드로 값을 가져와서 테이블에 뿌리고 있다

- '수정' 또는 '삭제' 를 클릭시 해당 회원의 아이디값을 넘기면서 updateForm.jsp 또는 delete.jsp 로 이동한다

- 관리자 모드이므로 '삭제' 누르면 바로 삭제되도록 했다

- 이 list() 메소드가 정의되어 있는 DAO 클래스의 부분을 보자

 

- MemberDao.java 에서 list() 메소드 부분만

	public List<Member> list() {
		List<Member> list = new ArrayList<Member>();
		SqlSession session=null;
		try { session = getSession(); 
			list = session.selectList("list");
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return list;
	}

- 제네릭을 쓰고 있으므로 리스트에서 get() 으로 가져올때 자료형 생략 가능

- SqlSession 객체를 구해와야만 selectList() 를 사용 가능하므로 getSession() 호출해서 SqlSession 객체 구해오기

- 메소드 getSession() 안에서 DB와 연동하는 것임

- List 객체 list 를 업캐스팅으로 생성

- selectList() 메소드는 검색되는 결과가 2개 이상인 경우 실행하는 메소드

- selectList() 메소드 첫번째 매개변수로 Mapper 파일의 id "list" 를 써서 해당 select SQL문을 호출

- selectList() 메소드에서 전달할 값은 없으므로 두번째 매개변수는 쓰지 않았다

- selectList() 메소드로 돌려받은 리스트를 객체 list 에 저장해서 list.jsp로 리턴

 

MyBatis 연동 전 / 후

- while(rs.next()) 에서 DTO 객체 생성하고 setter 메소드로 저장시킨 후 리스트에 객체를 저장하는 행동을 반복했다

- MyBatis 와 연동하면 이런 작업이 Mapping 을 통해서 자동으로 실행되고, 리스트를 반환시켜줌

 

selectOne() vs selectList()

- 돌려줄 데이터가 1개이면 selectOne() 사용, 2개 이상이면 selectList() 사용

- selectOne() 은 리턴자료형이 Object, selectList() 는 리턴자료형이 List

 

데이터를 2개 이상 검색해서 돌려줄때 주의사항

- Mapper 파일의 select 문에서 데이터를 2개이상 돌려주더라도 resultType 에는 리스트가 아니라 DTO 가 오면 된다

ex) 돌려주는 자료형이 List<int> 이더라도 resultType 에 List 가 아닌 int 를 씀

ex) 돌려주는 자료형이 List<DTO> 이면 resultType 에 List 가 아닌 DTO(alias 별칭 member) 를 씀

 

- Mapper 파일인 member.xml 에서 해당 SQL 문 부분만 살펴보자

- member.xml 에서 전체 목록을 가져오는 SQL문 부분

	<select id="list" resultType="member">
		select * from member22
	</select>

+ select는 반드시 resultType 을 써야함, 받을 값은 없으므로 parameterType 은 쓰지 않았다

- 전체 데이터를 검색하고 있다


정보수정 기능 : 수정폼

- list.jsp 에서 '수정' 을 눌렀을때 수정하는 기능

<td><input type="button" value="수정" onclick='location.href="updateForm.jsp?id=<%=list.get(i).getId() %>"'></td>

- '수정' 클릭시 onClick 에 의해 updateForm.jsp 로 넘어간다, 넘어갈 때 해당 회원의 id 값을 get 방식으로 전달

- 세션에 공유된 id값은 관리자 id값인 "master" 이고 여기서 넘어가는 id값은 각 회원의 id 값임

 

- 먼저 수정폼을 해야함

- updateForm.jsp 파일을 보자

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="model.Member"%>
<%@page import="dao.MemberDao"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

<%
	String id = request.getParameter("id");
	MemberDao md = new MemberDao();
	Member mem = md.select(id);
%>

<h2>정보 수정</h2>
<form action="updatePro.jsp">
	<input type="hidden" name="id" value="<%=mem.getId() %>">
	<table><tr><td>아이디</td>
			   <td><input type="text" name="id" value="<%=mem.getId() %>" disabled="disabled"></td></tr>
			<tr><td>암호</td>
				<td><input type="text" name="password" value="<%=mem.getPassword() %>"></td></tr>
			<tr><td colspan="2" align="right">
					<input type="submit" value="변경"> 
					<input type="button" onclick="history.go(-1)" value="취소"></td></tr>
	</table>
</form>

</body>
</html>

- 수정폼이므로 DB와 연동하여 1명에 대한 상세정보를 수정폼에 뿌려줘야한다

- list.jsp 에서 넘어온 회원의 id값을 받고 변수 id 에 저장

- DAO 객체를 생성해서 DAO 의 select() 메소드 호출

- select() 메소드를 호출하며 id 값을 넘긴다, 1명에 대한 상세정보를 구해오므로 리턴자료형 DTO

- 검색결과를 받은 mem 객체를 통해 mem.getId() 와 mem.getPassword() 로 id, password 를 수정폼에 뿌려줌

- id 는 disabled 로 설정되어있으므로 값이 action 의 페이지로 넘어가지 않는다, 그래서 hidden 객체로 따로 id 를 넘김

+ readonly 설정은 값이 넘어감, disabled 는 값이 안넘어감 * HTML readonly vs disabled 속성 설명 아래에

- 이후 수정폼에 상세정보를 뿌린 후, 사용자가 수정폼을 입력하고 '변경' 버튼을 누르면 id, password 를 가지고 updatePro.jsp로 이동한다

 

- MemberDao.java 에서 select() 메소드 부분만

	public Member select(String id) throws SQLException {
		Member mem = null;
		SqlSession session=null;
		try { session = getSession(); 
		mem = (Member) session.selectOne("select", id);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return mem;
	}

- getSession() 으로 SqlSession 객체 구해오기

- 1개 데이터를 검색하므로 selectOne() 메소드 호출

- 첫번째 매개변수에 들어가는 Mapper 파일의 id는 "select", 두번째 매개변수에 들어가는 전달될 값은 매개변수로 받은 id

- selectOne() 을 호출하고 결과를 Object 형으로 돌려주므로 다운캐스팅해서 DTO 객체 member 에 저장하고 그걸 리턴

+ 다운캐스팅 명시 생략 가능

- 이 select() 메소드 실행 후 이 메소드를 호출한 updateForm.jsp 로 돌아감  

 

- member.xml 에서 수정폼을 처리하는 SQL문 부분 (id 가 select)

	<select id="select" parameterType="String" resultType="member">
		select * from member22 where id = #{id}
	</select>

- 각 회원의 id 를 받으므로 paramterType 을 String 으로 설정

- 1명에 대한 상세정보를 리턴하므로 resultType 은 DTO 클래스 별칭인 member

- 전달되는 변수명이 id 이므로, #{id} 로 전달되는 값을 가져옴, parameterType 은 "String"

 

- URL 을 보면, id 값이 get 방식으로 넘어갔음을 볼 수 있다

 

+ 매개변수로 전달된 id 를 전달

- selectOne() 에서 변수 id 에 값이 전달되고 있다

- 그래서 member.xml 에서 #{id} 로 SQL문 where절 작성


정보수정 기능 : 실제 수정

- 이후 수정폼에 상세정보를 뿌린 후, 사용자가 수정폼을 입력하고 '변경' 버튼을 누르면 id, password 를 가지고 updatePro.jsp 로 이동한다

 

- updatePro.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="dao.MemberDao"%>
<%@page import="model.Member"%>

<jsp:useBean id="mem" class="model.Member"/>
<jsp:setProperty property="*" name="mem"/>

<%
	MemberDao md = new MemberDao();
	int result = md.update(mem);

if (result == 1) {
%>
	<script type="text/javascript">
		alert("수정 성공");
		location.href="list.jsp";
	</script>
<%
} else {
%>
	<script type="text/javascript">
		alert("수정 실패");
		history.go(-1);
	</script>
<%
}
%>

- useBean, setProperty action tag 사용해서 수정폼에서 hidden 으로 넘어온 id 값과, 비밀번호 입력양식에서 넘어온 password 값을 받아서 DTO 객체 mem 에 저장

+ 입력양식의 name 값과 DTO 의 프로퍼티명이 일치할때만 가능

- DAO 객체 생성 후 DAO의 update() 메소드를 호출하며 매개변수로 객체 mem 을 전달

- 성공시 메세지 출력 후 list.jsp 로 돌아감, 즉 다시 회원목록을 구해서 뿌려준다

 

- MemberDao.java 에서 update() 메소드 부분만

	public int update(Member mem) {
		int result = 0;
		SqlSession session=null;
		try { session = getSession(); 
			result = session.update("update", mem);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

- update() 메소드의 첫번째 매개변수에 Mapper 파일의 id 명인 "update" 를, 두번째 매개변수에 넘겨줄 값인 객체 mem 을 적기

- update() 메소드가 실행되고 성공적으로 수정하면 1 을 리턴해줌, 그 1 을 result 변수에 저장해서 updatePro.jsp 로 리턴함

 

- member.xml 에서 정보 수정을 처리하는 SQL문 부분 (id 가 update)

	<update id="update" parameterType="member">
		update member22 set password = #{password} where id = #{id}
	</update>

- DTO 객체가 넘어올때 #{id} 는 member.getId() 를 의미, #{password} 는 member.getPassword() 를 의미

- update SQL문이 수행되고 자동으로 수정한 데이터 개수를 돌려줌, 즉 1 을 리턴해줌


* HTML readonly vs disabled 속성

 

공통점

- 입력 양식의 값을 수정할 수 없도록 비활성화 시켜주는 역할

차이점

- readonly 속성으로 설정된 양식은 action 으로 설정된 페이지로 값이 전달되지만,
- disabled 속성으로 설정된 양식은 action 으로 설정된 페이지로 값이 전달되지 않는다.


정보수정 기능 : 삭제

- list.jsp 에서 '삭제' 를 눌렀을때 수정하는 기능

<td><input type="button" value="삭제" onclick='location.href="delete.jsp?id=<%=list.get(i).getId() %>"'></td></tr>

- '삭제' 클릭시 onClick 에 의해 delete.jsp 로 넘어간다, 넘어갈 때 해당 회원의 id 값을 get 방식으로 전달

- 즉 삭제폼을 거치지 않고 바로 삭제되게 해뒀다

 

- delete.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@page import="dao.MemberDao"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
String id = request.getParameter("id");
MemberDao md = new MemberDao();
int result = md.delete(id);
if (result == 1) {
	%>
	<script type="text/javascript">
	alert("삭제성공");
	location.href="list.jsp";
	</script>
	<%
} else {
	%>
	<script type="text/javascript">
	alert("실패");
	location.href="list.jsp";
	</script>
	<%
}
%>
</body>
</html>

- list.jsp 로 부터 전달받은 id 값을 받아서 저장

- DAO 객체를 생성하고 DAO의 delete() 메소드 실행, 특정 회원 삭제를 해야하므로 매개변수로 id 값을 전달한다

- 메소드 호출하여 삭제 성공시 목록 페이지인 list.jsp 로 돌아간다

 

- MemberDao.java 에서 delete() 메소드 부분만

	public int delete(String id) {
		int result = 0;
		SqlSession session=null;
		try { session = getSession(); 
			result = session.delete("delete", id);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return result;
	}

 

- member.xml 에서 회원 삭제(탈퇴) 를 처리하는 SQL문 부분 (id 가 delete)

	<delete id="delete" parameterType="String">
		delete from member22 where id = #{id}
	</delete>

- #{id} 는 DAO에서 session.delete() 메소드 실행시 두번째 매개변수로 넘어온 변수 id 를 의미함

- delete SQL문이 수행되고 자동으로 삭제한 데이터 개수를 돌려줌, 즉 1 을 리턴해줌

- 자동으로 삭제한 데이터 개수를 돌려주므로 select 외의 insert/update/delete 는 returnType 을 쓰면 안된다

 

#{id} 의 의미

1. 일반 변수 id 가 넘어왔을때 #{id} 는 그 변수 id 값을 의미함

2. DTO 객체 member 가 넘어왔을때 #{id} 는 member.getId() 를 의미, 즉 객체 안의 프로퍼티 값을 의미

- 같은 코드지만 다른 의미이다

 

- master 로 로그인 한 뒤 회원 목록 페이지인 list.jsp 에서 회원을 삭제해보자

 


MyBatis

- DB 연동을 처리하기 위한 프레임 워크

 

프로그램 확장 시

- MyBatis 환경설정 파일은 하나만 있으면 된다

- Mapper 파일은 테이블의 개수에 비례해서 늘어난다

 

태그 맞추기

- Mapper 파일인 member.xml의 루트 엘리먼트는 mapper 이다

- MyBatis 환경 설정 파일에서 태그를 mapper 로 해야한다

- Mapper 파일의 루트 엘리먼트와 MaBatis 환경설정 파일에서 Mapper 파일을 불러올때 태그 이름을 맞춰야한다

 

Mapper 파일의 id 충돌문제

- 같은 Mapper 파일 뿐 아니라 다른 Mapper 파일 끼리도 id 값을 다르게 설정해야한다

- member 테이블, board 테이블 이 있을때 member.xml , board.xml 처럼 Mapper 파일이 각각 생성됨

- 이때 서로 다른 두 Mapper 파일에서도 같은 id값을 쓰면 안된다!, 그래야 DAO에서 불러올때 충돌되지 않음

- id 값이 중복되는 문제 해결하기 위해 namespace

 

namespace

- 논리적인 영역 이름

- namespace를 통해 id값 중복되어 DAO 에서 불러올때 충돌되는 문제 해결가능

+ 일반적으로 namespace를 테이블명+"ns" 로 설정함

- Mapper 파일에서 namespace 값만 서로 다르게 설정하면 다른 Mapper 파일끼리 같은 id값을 사용할 수 있다

- Mapper 파일인 member.xml 부분

- 그래서 insert id 를 불러오는 DAO 코드에서 namespace 를 함께 써서 충돌 피할 수 있다

- 이렇게 하면 다른 테이블의 Mapper 파일에서 id 값을 insert 로 쓴다고 해도 충돌하지 않음

+ Recent posts