inderrom 2022. 12. 6. 01:11

iBatis란

- JAVA에서 DB를 편하게 핸들링할 수 있게 해주는 프레임워크이다.
- SQL문과 Java소스코드를 분리하고, 파라미터 값만 같으면 Java소스코드 변경 없이
 사용할 수 있다.
- iBatis 데이터 매퍼 API를 사용해서 자바빈즈(보통 VO객체)혹은 Map객체를
  PreparedStatement의 파라미터에 매핑 해주고 SQL문의 실행 결과를 
  자바빈즈 혹은 Map객체에 자동으로 매핑해준다.

 

1. SqlMqpConfig  설정 - mxl 문서

 

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

<!--  이 문서는 iBatis의 환경 설정 내용을 가지고 있는 xml문서 -->

<!DOCTYPE sqlMapConfig
	PUBLIC "-//ibatis.apache.org//DTD DQL Map Config 2.0//EN"
	"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
	<!-- 
		DB와 연결하는 정보를 .properties파일에 저장해 놓고
		이 .properties파일의 내용을 읽어 올 수 있도록 설정한다.
	-->
		 <properties resource="kr/or/ddit/ibatis/config/dbinfo.properties"/>
		 
	<!-- 
		각각의 sqlMap파일의 namespace 속성값과 id 속성값을 연결해서
		실행할 SQL문을 선택할 수 있게 한다.	 
	 -->
	 <settings useStatementNamespaces="true"/>

	<!-- 
		SQL문에 사용할 VO객체는 패키지 이름을 포함한 전체 이름을 사용해야 한다.
		그렇게 되면 문장이 너무 길어질 수 있기 때문에 이 전체 이름을 대신해서 사용할
		alias를 설정할 수 있다.
		
		형식) <typeAlias alias="사용할alias명" type="사용할 클래스의 전체이름"/>
	 -->
	 	<typeAlias alias="lprodVo" type="kr.or.ddit.vo.LprodVO"/>
	 
	 <!-- 
	 	DB와의 연결을 처리하는 부분
	  -->
	  <transactionManager type="JDBC">
	  	<dataSource type="SIMPLE">
	  		<property name="JDBC.Driver" value="${driver}"/>
	  		<property name="JDBC.ConnectionURL" value="${url}"/>
	  		<property name="JDBC.Username" value="${user}"/>
	  		<property name="JDBC.Password" value="${pass}"/>
	  	</dataSource>
	  </transactionManager>
	
	 <!-- 
		실행할 SQL문 등록하기
		==> 실행할 SQL문은 xml문서로 따로 만든 후 그 xml문서를 아래와 같이 등록하면 된다.
		
		형식) <sqlMap resource="경로명/파일명.xml"/>
	  -->
	  <sqlMap resource="kr/or/ddit/ibatis/mapper/lprodTest-mapper.xml"/>


</sqlMapConfig>

 

 

 

2. VO 객체 생성 ( src에 vo패키지에 생성한다)

 

package kr.or.ddit.vo;

public class LprodVO {
   private int lprod_id;
   private String lprod_gu;
   private String lprod_nm;
   
   public int getLprod_id() {
      return lprod_id;
   }
   public void setLprod_id(int lprod_id) {
      this.lprod_id = lprod_id;
   }
   public String getLprod_gu() {
      return lprod_gu;
   }
   public void setLprod_gu(String lprod_gu) {
      this.lprod_gu = lprod_gu;
   }
   public String getLprod_nm() {
      return lprod_nm;
   }
   public void setLprod_nm(String lprod_nm) {
      this.lprod_nm = lprod_nm;
   }
   
}

 

 

 

3.  mapper 작성

 

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


<!-- 이 문서는 iBatis에서 처리할 SQL문을 작성하는 문서입니다. -->

<!DOCTYPE sqlMap
	PUBLIC "-//ibatis.apache.org/DTD SQL Map 2.0//EN"
	"http://ibatis.apache.org/dtd/sql-map-2.dtd">
	
<sqlMap namespace="lprod">
	<!-- 
		이 영역에는 처리할 SQL문에 맞는 태그를 사용해서 SQL문을 작성한다.
		
		사용할 수 있는 기본적인 태그들... (이것말고도 여러개 있음)
		<select> 처리할 select문 </select>
		<insert> 처리할 insert문 </insert>
		<delete> 처리할 delete문 </delete>
		<update> 처리할 update문 </update>
		
		...
	 -->
	 
	<!-- 
		id속성 ==> 실행할 태그를 Java 소스에서 호출할 때 사용되는 이름으로
			<sqlMap>태그의 namespace 속성값과 연결해서 사용한다.
			(예: 'lprod.insertLprod')
		parameterClass속성 ==> SQL문에 사용될 데이터가 저장된 객체를 기술한다.
			(보통 VO클래스, 또는 Java의 기본 자료형이름, Map객체 등이 사용된다.
			<VO클래스 등을 기술할 때는 해당 클래스의 전체 이름을 기술하거나 등록된 alias명을 기술한다.)	
			
		preparedStatement에서 사용했던 ? 대신 VO 객체의 변수명을 ## 사이에 작성한다.
		#변수명#	
	 -->
	 
	 
	 <insert id="insertLprod" parameterClass="kr.or.ddit.vo.LprodVO">
	 	insert into lprod(lprod_id, lprod_gu, lprod_nm)
	 	values(#lprod_id#, #lprod_gu#, #lprod_nm#)
	 </insert>
	 
	 <!-- parameterClass속성에 <typeAlias>에 등록한 alias명을 사용할 수 있다. -->
	 
	 <update id="updateLprod" parameterClass="lprodVo">  
	 	update lprod set lprod_id=#lprod_id#, lprod_nm=#lprod_nm#
	 	where lprod_gu=#lprod_gu#
	 </update>
	 
	 <!-- 
	 	parameterClass속성에 설정되는 값이 단일 값이면 
	 	SQL문에 이 값을 나타내는 변수명은 특별히 이름이 정해지지 않는다.
	 	(즉, 사용자 임의로 지정할 수 있다.)
	 	(단일값이면 parameterClass에 java의 기본 자료형 이름을 쓸 수 있다.)
	  -->
	 <delete id="deleteLprod" parameterClass="string">
	 	delete from lprod where lprod_gu=#lprod_gu#
	 <!-- delete from lprod where lprod_gu=#asdf#  << 이렇게도 된다-->
	 </delete>
	
	 <!-- 
	 	resultClass ==> select문을 처리할 때 반드시 지정하는 속성으로 select문의 처리 결과를 저장 할
	 					VO클래스나 Map클래스, 그리고 자바의 기본 자료형이름을 지정한다.
	 			select문을 처리한 결과가 1개 또는 여러개여도 이 속성에 설정하는 것은
	 			1개의 레코드가 저장될 클래스나 자료형 이름을 지정하면 된다.
	 			( 이유 : 결과가 여러개일 경우에는 iBatis에서 자동으로 List에 담아 줄 수 있다.)
	  -->

	 <select id="getAllLprod" resultClass="lprodVo">
		select * from lprod
	 </select>
	 
	 <select id="getLprod" parameterClass="string" resultClass="lprodVo">
	 	select * from lprod where lprod_gu =#lprod_gu#
	 </select>
	 

</sqlMap>

 

4. 실행하기

 

package kr.or.ddit.basic;

import java.io.Reader;
import java.nio.charset.Charset;
import java.sql.SQLException;
import java.util.List;
import java.util.Scanner;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

import kr.or.ddit.vo.LprodVO;

public class LprodIbatisTest {
	
	// iBatis를 이용하여 DB자료를 처리하는 방법 및 순서
	
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		
		SqlMapClient smc = null;
		
		// 1. iBatis의 환경 설정 파일을 읽어와서 실행한다. (sqlMapConfig.xml)
		try {
			// 1-1 문자 인코딩 캐릭터셋 설정
			Charset charset = Charset.forName("UTF-8");
			Resources.setCharset(charset);
			
			// 1-2. 환경 설정 파일 읽기
			Reader rd = 
				Resources.getResourceAsReader("kr/or/ddit/ibatis/config/sqlMapConfig.xml");
			
			// 1-3. 위에서 읽어온 Reader객체를 이용하여 실제 환경 설정을 완성한 후에
			// 		SQL문을 호출해서 실행할 수 있는 객체를 생성한다.
			smc = SqlMapClientBuilder.buildSqlMapClient(rd);
			
			rd.close(); // Reader객체 닫기
			
		} catch (Exception e) {
			System.out.println("iBatis 환경 설정 오류 ....");
			e.printStackTrace();
		}
		//--------------------------------------------------------------
		
		// 2. 실행할 SQL문에 맞는 쿼리문을 호출해서 원하는 작업을 수행한다.
		try {
			/*
			// 2-1. insert연습
			System.out.println("insert 작업 시작...");
			System.out.println("Lprod_id 입력 >> ");
			int num = scan.nextInt();
			
			System.out.println("Lprod_gu 입력 >> ");
			String gu = scan.next();
			
			System.out.println("Lprod_nm 입력 >> ");
			String nm = scan.next();
			
			// 1) 입력 받은 자료를 VO객체에 저장한다.
			LprodVO lvo = new LprodVO();
			lvo.setLprod_id(num);
			lvo.setLprod_gu(gu);
			lvo.setLprod_nm(nm);
			
			// 2) sqlMapClient객체 변수(smc)를 이용하여 처리할 SQL문을 호출하여 실행한다.
			// 형식) smc.insert("namespace속성값.id속성값", 파라미터클래스)
			//		==> 반환값 : insert성공 : null, insert실패 : 오류객체 << 숫자가 중요한 게 아니라 ~Exception 때문에 Object를 써준다.
			Object obj = smc.insert("lprod.insertLprod", lvo);
			if(obj==null) {
				System.out.println("insert 작업 성공!!!");
			}else {
				System.out.println("insert 작업 실패~~~");
			}
			System.out.println("--------------------------------------------");
			*/
			
			/*
			// 2-2. update연습
			System.out.println("update 시작...");
			
			System.out.print("수정할 Lprod_gu 입력 >>");
			String lgu = scan.next();
			
			System.out.print("새로운 Lprod_id 입력 >>");
			int lid= scan.nextInt();
			
			System.out.print("새로운 Lprod_nm 입력 >>");
			String lnm= scan.next();
			
			// 1) 입력 받은 자료를 VO객체에 저장한다.
			LprodVO lvo2 = new LprodVO();
			lvo2.setLprod_id(lid);
			lvo2.setLprod_gu(lgu);
			lvo2.setLprod_nm(lnm);			
			
			// 2) 쿼리문 실행하기
			// 형식) smc.update("namespace속성값.id속성값", 파라미터클래스)
			//		==> 반환값 : 작업에 성공한 레코드 수
			int cnt = smc.update("lprod.updateLprod", lvo2);
			
			if(cnt>0) {
				System.out.println("update 작업 성공!!!");
			}else {
				System.out.println("update 작업 실패~~");
			}
			System.out.println("--------------------------------------------");
			*/
			
			/*
			// 2-3. delete연습
			System.out.println("delete 작업 연습...");
			System.out.print("삭제할 Lprod_gu 입력 >> ");
			String lgu2 = scan.next();
			
			// 1) 쿼리문 실행하기
			// 형식) smc.delete("namespace속성값.id속성값", 파라미터클래스)
			//		==> 반환값 : 작업에 성공한 레코드 수 
			int cnt2 = smc.delete("lprod.deleteLprod", lgu2);
			
			if(cnt2>0) {
				System.out.println("delete 작업 성공!!!");
			}else {
				System.out.println("delete 작업 실패~~~");
			}
			System.out.println("--------------------------------------------");
			*/
			
			/*
			// 2-4. select연습
			
			// 1) select한 결과가 여러개인 경우
			System.out.println("select 연습 시작 (결과가 여러개일 경우)...");
			
			// select한 결과가 여러개일 경우에는 queryForList()메서드를 사용하는 데
			// 이 메서드는 여러개의 레코드 각각을 VO에 담은 후 이 VO객체를 List에 추가해 주는
			// 작업을 자동으로 수행한다.
			// 형식) smc.queryForList("namespace속성값.id속성값", 파라미터클래스)
			//		반환값 ==> 데이터가 저장된 List객체
			List<LprodVO> lprodList = smc.queryForList("lprod.getAllLprod");
			
			for(LprodVO lvo3 : lprodList) {
				System.out.println("Lprod_id : " + lvo3.getLprod_id());
				System.out.println("Lprod_gu : " + lvo3.getLprod_gu());
				System.out.println("Lprod_nm : " + lvo3.getLprod_nm());
				System.out.println("------------------------------------");
			}
			System.out.println("출력 끝...");
			System.out.println("====================================");
			*/
			
			// 2) select한 결과가 1개일 경우
			System.out.println("select 연습 시작(결과가 1개일 경우)...");
			
			System.out.print("검색할 Lprod_gu 입력 >> ");
			String lgu3 = scan.next();
			
			// select한 결과가 1개일 경우에는 queryForObject()메서드를 사용한다.
			// 형식) smc.queryForObject("namespace속성값.id속성값", 파라미터클래스)
			//		반환값 : 1) 쿼리문의 결과가 여러개일 경우 ==> Exception객체
			//				 2) 쿼리문의 결과가 1개일 경우 ==> 검색한 객체 (정상)
			//			     3) 쿼리문의 결과가 없을 경우 ==> null
			
			// object라 형변환을 해줘야한다.
			LprodVO lprodVo = (LprodVO)smc.queryForObject("lprod.getLprod", lgu3);
			
			if(lprodVo==null) {
				System.out.println("검색한 결과가 하나도 없습니다...");
				return;
			}
			System.out.println("-- 검색 결과 --");
			System.out.println("Lprod_id : " + lprodVo.getLprod_id());
			System.out.println("Lprod_gu : " + lprodVo.getLprod_gu());
			System.out.println("Lprod_nm : " + lprodVo.getLprod_nm());
			
			System.out.println("------------------------------------");
			
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}

}