티스토리 뷰


복습 : Bean 등록 방법에는 생성자를 이용한 방법, setMethod 를 이용한 방법 두 가지가 있다.

많은 댓글과 조언이 제 공부에 도움이 됩니다 ^~^

****************************************************************************************

Persistence Layer (영속성 계층)

ORM Framework

 - Hibernate

Mapper Framework

 -  Mapper Framework

 - ibatis, Mybatis

 - DAO의 메소드와 XML문서의 Element 와 Mapping 해주는 것

 

IBatis

1. Spring 환경에서 사용할 수 있도록 라이브러리 검색

 - mavenrepository.com -> spring orm 검색 -> 해당 dependancy 복사 -> pom.xml 등

 - bean 등록 -> property 설정 

sqlMapClient

 - 직접 ibatis 에서 사용 해야 하는 명령어를 따로 익혀야 한다.

 - DB 접속 Bean 과 연결을 해줘야 한다.( dataSource )

sqlMapClientTemplate

 - property로 sqlMapClient 를 setting 할 수 있다.

 - Spring이 제공해주는 명령어를 사용하면 된다.


 - 스프링 설정 파일 ( dispatcher-servlet.xml or root.xml or 해당 bean.xml )

<bean id="dataSource" p:password="1111" p:username="abcd"
	p:url="jdbc:oracle:thin:@127.0.0.1:1521:xe" p:driverClassName="oracle.jdbc.driver.OracleDriver"
	destroy-method="close" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" />
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
	<property name="configLocation" value="classpath:sqlMapConfig.xml"/>
	<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
	<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>

위의 dataSource 는 P tag를 이용해 작성하였다. DB 접속 bean 과 ibatis Bean 을 연동함으로써 DB 접속의 관련된 내용은 구현이 완료 되었다. 이제, ibatis를 이용하여 쿼리를 작성하여 결과를 얻기 위한 방법을 보자.

다음은 sqlMapClient 에서 /WEB-INF/ibatis/sqlMapConfig.xml 를 작성해 줘야 한다.

이 xml 파일은 쿼리가 작성될 문서를 등록하는 파일이다. 아래와 같이 작성한다.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" 
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
	<settings useStatementNamespaces="true"/>
	<sqlMap resource="bbs.xml"/>
</sqlMapConfig>

쿼리에 대한 내용이 작성될 bbs.xml 을 sqlMapConfig 태그 안에 작성하였다. 실질적인 쿼리는 bbs.xml에 작성될 것이다.

게시판의 관련된 모든 쿼리를 작성한 bbs.xml의 내용을 살펴보자.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd">

<sqlMap>

	<typeAlias alias="article" type="com.ktds.bbs.vo.BoardVO" />
	<typeAlias alias="comment" type="com.ktds.comment.vo.CommentVO" />

	<!-- Get All articles count -->
	<select id="getArticleCount" resultClass="int">
		select count(*) from bbs
	</select>

	<!-- Get All articles -->
	<select id="getArticles" parameterClass="HashMap" resultClass="article">
		select article_num, id, title, depth, hit, write_date
		from ( select rownum rm, bbs.* from
		( select * from bbs order by group_id desc, pos) bbs )
		where rm between #StartRow# and #EndRow#
	</select>

	<!-- Get Article -->
	<select id="getArticle" parameterClass="Integer" resultClass="article">
		select * from bbs where article_num = #article_num#
	</select>
	
	<!-- Get Article For Update -->
	<select id="getArticleForUpdate" parameterClass="String" resultClass="article">
		select article_num, id, hit, title, content, fname from bbs where article_num = #article_num#
	</select>
	
	<!-- When Get article, Hit up -->
	<update id="updateHit" parameterClass="Integer">
		update bbs set hit = hit+1
		where article_num = #article_num#
	</update>

	<!-- Login check -->
	<select id="loginCheck" parameterClass="String" resultClass="String">
		select pass from login where id=#id#
	</select>

	<!-- Insert Article -->
	<insert id="insertArticle" parameterClass="article">
		INSERT INTO bbs (ARTICLE_NUM, ID, TITLE, CONTENT, HIT, GROUP_ID, POS, DEPTH, WRITE_DATE, FNAME)
		VALUES ( bbs_seq.nextval,
		#id#, #title#, #content#, 0, bbs_seq.currval, 0, 0, sysdate, #fname#)
	</insert>
	
	<!-- Update Article -->
	<update id="updateArticle" parameterClass="article">
		update bbs set title=#title#, content=#content#, fname=#fname# where article_num=#article_num#
	</update>
	
	<!-- Delete Article -->
	<delete id="deleteArticle" parameterClass="String">
		delete bbs where article_num = #article_num#
	</delete>
	
	<!-- insertReply -->
	
	<update id="updatePos" parameterClass="HashMap">
		update bbs set pos = pos+1 where group_id = #group_id# and pos > #pos#
	</update>
		
	<insert id="insertReply" parameterClass="article">
		INSERT INTO bbs (ARTICLE_NUM, ID, TITLE, CONTENT, HIT, GROUP_ID, POS, DEPTH, WRITE_DATE, FNAME) 
		VALUES ( bbs_seq.nextval, #id#, #title#, #content#, 0, #group_id#, #pos#, #depth#, sysdate, #fname#) 
	</insert>
	
</sqlMap>

자바 소스에서 id 로 맵핑(호출)하여 사용할 것이기 때문에 id를 의미 있게 설정을 한다.

여기서 parameterClass 와 resultClass 를 볼 수 있다. 두 가지 외에 더 많은 속성들이 있지만, 일단 두 속성을 설명하면

parameterClass 는 쿼리에 넣을 입력 값의 클래스를 정의하고, resultClass 는 쿼리 후 결과를 받을 클래스를 정의한다.

article 의 경우는 ...BoardVO.java 를 alias 를 통해 사용하기 쉽게 정의한 것이다.

자바 소스를 같이 살펴 보면 이해하기 더 쉬울 테니 자바 소스 코드를 살펴 본다.

package com.ktds.bbs.dao;

import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.stereotype.Repository;

import com.ktds.bbs.vo.BoardVO;

@Repository
public class BBSOracleDAO implements BBSDaoService {

	@Autowired
	SqlMapClientTemplate smct;

	@Override
	public int getArticleCount() {
		return (int) smct.queryForObject("getArticleCount");
	}

	@Override
	public List<BoardVO> getArticles(int StartRow, int EndRow) {
		// 게시글 가져오 는 SQL 쿼리문

		HashMap<String, Integer> hm = new HashMap<>();
		hm.put("StartRow", StartRow);
		hm.put("EndRow", EndRow);
		return smct.queryForList("getArticles", hm);
	}

	public void insertArticle(BoardVO article) {

		smct.insert("insertArticle", article);
	}

	// 글 내용 읽어들이기
	public BoardVO getArticle(String article_num2) {

		// 게시물 번호로 조회하는 쿼리문
		int article_num = Integer.parseInt(article_num2);

		smct.update("updateHit", article_num);

		BoardVO article = (BoardVO) smct.queryForObject("getArticle", article_num);

		// 읽어온 게시물 반환
		return article;
	}

	public BoardVO getArticleForUpdate(String article_num) {

		// 게시물 번호로 조회하는 쿼리문
		return (BoardVO) smct
				.queryForObject("getArticleForUpdate", article_num);

	}

	public void updateArticle(BoardVO article) {

		smct.update("updateArticle", article);
	}

	public int login_check(String id, String pass) {

		String result = (String) smct.queryForObject("loginCheck", id);

		int status = 0;

		if (result != null) {
			if (pass.equals(result)) {
				status = 1;
			} else {
				status = 2;
			}
		} else {
			status = 3;
		}
		return status;
	}

	public void insertReply(BoardVO article) {
		
		HashMap<String, Integer> hm = new HashMap<>();
		hm.put("group_id", article.getGroup_id());
		hm.put("pos", article.getPos());
		smct.update("updatePos", hm);

		article.setPos(article.getPos()+1);
		article.setDepth(article.getDepth()+1);
		
		smct.update("insertReply", article);
	}

	public void deleteArticle(String article_num) {

		smct.delete("deleteArticle", article_num);
	}
}

Spring에서 제공하는 ibatis를 사용하기 위한 SqlMapClientTemplate 클래스를 이용한다.

JDBCTempalate을 이용한 방법은 약간 다르다. JDBCTemplate 에서는 모든 글을 가져올 때, Query를 사용 하였지만, SqlMapClientTemplate 에서는 QueryForList를 사용하는 약간의 차이가 있다.

 QueryForObject - 하나의 값을 가져올 때 사용

 QueryForList - 복수개의 레코드를 가져올 때 사용

모든 게시글을 가지고 오는 getArticles() 함수를 살펴 보면, List를 반환 해야 하므로, QueryForList 함수를 사용한다. 페이지의 시작과 끝을 이용하여 게시글을 가져올 것이고, 두 개의 변수를 담을 HashMap 을 선언하고, HashMap 에 put 함수를 이용하여, 값을 두 개 넣었다. 

그리고, smct.queryForList("getArticles", hm) 을 분석하자면, 왼쪽 인수는 xml에 정의한 쿼리 id 가 될 것이고, 오른쪽은 parameterClass에 정의한 클래스와 맞는 HashMap hm 을 인수로 넣었다. 현재 hm 은 StartRow 와 EndRow 두 개의 값을 가지고 있는 것이다.

이제 id에 맞는 쿼리가 실행 될 것이고, 쿼리에서는 넘어온 값을 Map 의 Key 값을 이용하여 호출 할 수 있다.

실제 쿼리는 아래의 소스 코드와 같고, hm 의 담겨진 값을 #StartRow#, #EndRow# 로 사용하는 것을 볼 수 있다.

select article_num, id, title, depth, hit, write_date
 from ( select rownum rm, bbs.* from
 ( select * from bbs order by group_id desc, pos) bbs )
 where rm between #StartRow# and #EndRow#

나머지 동작 과정은 방금 설명한 것과 거의 동일하다. 


주의할 점은 select 문은 select Tag, insert 문은 Insert Tag 등을 맞춰주어야 하는 것 뿐!

또한 반환 값이 있을 땐 resultClass 를 써주고 클래스를 맞춰주어 사용하고, 반환 값이 없을 땐 resultClass를 생략하면 된다.

************************************************************************************************************

부족한 설명이 있거나 잘 못된 부분이 있으면 댓글을 남겨 주세요^~^


댓글