Java - 10. iBATIS

갓김치·2020년 10월 7일
0

고급자바

목록 보기
29/47

들어가기 전

JDBC 단점

  • conn, stmt, pstmt, rs 변수 선언하고
  • try-catch 메서드마다 계속나오고
  • 쿼리 날리고
  • finally로 자원반납해줘야하고
  • 반복되는 쿼리도 너무 많아ㅏㅏ~~ 코드너무길어~~

프레임워크 장점

  • d(≧▽≦d) 유지보수 조아요 (b≧▽≦)b

iBATIS

  • 데이터베이스에 있는 자원들을 보다 편리하게 가져오기 위한 프레임워크
  • JDBC의 반복적인 작업을 iBATIS가 해줌
  • SQL 매퍼 + DAO 프레임워크
  • 프레임워크를 사용하기위해서는 xml이나 properties파일로 환경설정을 미리 해줘야함

특징

  • 코드와 SQL 분리를 통한 생산성 향상
    • JDBC와 SQL를 유지하면서도 훨씬 더 적은 코드로 JDBC처럼 작동
    • 유지보수시 Java코드 말고 다른거 고쳐도됨
  • 추상화된 접근방법
    • JDBC 프로그래밍에 필수적인 자원의 연결/해제 및 공통 에러처리 등을 통합 지원함으로써 쿼리의 실행에만 집중할 수 있는 추상화 제공

관련 소스 파일

SqlMapConfig.properties

  • DB와 연결하는 정보를 properties 파일에 설정

SqlMapConfig.xml

< sqlMapConfig > 내부

< properties >

<properties resource="SqlMapConfig.properties" />
  • DB 연결 정보가 담긴 properties파일의 내용을 읽어와 설정한다.

< settings >

<settings cacheModelsEnabled="true"
          enhancementEnabled="true"
          lazyLoadingEnabled="true"
          maxRequests="32"
          maxSessions="10"
          maxTransactions="5"
          useStatementNamespaces="true" />
  • ibatis를 처리하기 위한 환경설정 부분
    • useStatementNamespaces="true": VO담는 xml에 별칭 부여하겠다

< typeAlias >

<typeAlias alias="memVO" type="kr.or.ddit.member.vo.MemberVO"/>
  • typeAlias: 타입에 대한 별칭
  • 클래스 이름이 패키지명까지 기술할 때, 이것을 간단히 표시하기 위해서 alias를 지정
  • 형식: <typeAlias alias="alias명" type="클래스의 풀네임"/>

< transactionManager type="JDBC" >

  • DB와의 연결을 처리하는 부분
  • SqlMapConfig.properties에 설정해 놓은 정보를 이용하여 구성
    • SIMPLE => SimpleDataSourceFactory
      • 데이터소스를 제공하는 컨테이너가 없는 경우 connection을 제공하기 위해 기본적으로 pooling 데이터소스 구현을 제공
      • iBATIS SimpleDataSource connection pooling을 기반으로 한다.
    • DBCP => DbcpDataSourceFactory
      • DataSource API를 통해 connection pooling 서비스를 제공하기 위해 DBCP를 사용한다.
      • 이 DataSource는 어플리케이션/웹 컨테이너가 DataSource 구현물을 제공하지 못하거나 standalone 어플리케이션을 구동할 때 이상적
    • JNDI => JndiDataSourceFactory
      • 어플리케이션 컨테이너 내 JNDI 컨텍스트로부터 DataSource 구현물을 가져와야 한다.
      • 이것은 어플리케이션 서버를 사용중이고 컨테이너 관리 connection pool과 DataSource가 제공될 때 사용한다.
      • JDBC DataSource 구현물에 접근하기 위한 표준적인 방법은 JNDI 컨텍스트를 통하여 접근하는 것
<transactionManager type="JDBC">
  <dataSource type="SIMPLE">
    <property name="JDBC.Driver" value="${driver}" />
    <property name="JDBC.ConnectionURL" value="${url}" />
    <property name="JDBC.Username" value="${username}" />
    <property name="JDBC.Password" value="${password}" />
  </dataSource>
</transactionManager>
  • 각종 설정을 직접 기술해서 처리할 수 있으나 그런 하드코딩방식은 적합하지 않음

< sqlMap >

<sqlMap resource="kr/or/ddit/sqlmap/member.xml"/>
  • 실제 처리할 SQL문의 xml문서를 따로 만든 후 이 태그로 연결하여 사용한다.
  • 형식: <sqlMap resource="경로명/파일명.xml"/>

member.xml

  • 쿼리를 별도로 관리하는 파일

SQL 기본 태그

  • select, insert, update, delete
    • select
      • 성공시 객체반환 (queryForList, queryForObject)
      • 동적쿼리: <isNotEmpty> 사용 (아래 예시 참고)
    • insert: 성공시 null 반환
    • update, delete: 성공시 행의 갯수 반환

SQL 기본 태그의 속성

  • id
    • 해당 태그를 호출할 때 <sqlMap>태그의 namespace와 연결하여 사용하는 이름
  • parameterClass
    • sql문에 사용될 데이터가 들어있는 객체를 지정
    • 보통 VO클래스, 자바의 자료형 이름등이 사용됨
    • typeAlias로 지정한 alias명을 사용할 수 있음
    • 생략 가능
  • resultClass
    • select 문을 실행한 결과를 담을 객체
    • 보통 VO클래스, 자바의 자료형 이름
    • resultMap으로 대체 가능
    • 생략 불가

<sqlMap> 내부

  • namespace를 "member"로 설정
    • 이 파일의 SQL을 호출할 때 같이 사용됨
  • ##: 스트링이면 '', int면 ''없이 그냥 대입
  • $$: 내가 넣는 데이터 그대로 삽입

<resultMap>

<resultMap class="memVO" id="memberMap">
  <result property="memId" column="mem_id"/>
  <result property="memName" column="mem_name"/>
  <result property="memTel" column="mem_tel"/>
  <result property="memAddr" column="mem_addr"/>
</resultMap>
  • VO클래스의 변수명과 DB 테이블의 컬럼명을 매핑
  • 이렇게 하지 않으면 iBatis가 데이터를 읽어온 것과 꺼내는거랑 매칭이 안되서 null 파티

<select>

<select id="getMemberAll" resultMap="memberMap">
  SELECT * FROM MYMEMBER
</select>

<select id="getMember" resultMap="memberMap">
  SELECT * FROM MYMEMBER WHERE MEM_ID = #memId#	
</select>

<select id="getSearchMember" parameterClass="memVO" resultMap="memberMap">
  SELECT * FROM MYMEMBER
  WHERE 1=1
  <isNotEmpty property="memId">
    AND MEM_ID = #memId# 
  </isNotEmpty>
  <isNotEmpty property="memName">
    AND MEM_NAME = #memName#
  </isNotEmpty>
  <isNotEmpty property="memTel">
    AND MEM_TEL = #memTel#
  </isNotEmpty>
  <isNotEmpty property="memAddr">
    AND MEM_ADDR LIKE '%' || #memAddr# || '%' 
  </isNotEmpty>
</select>
  • <isNotEmpty>★
    • null, 0이 아닐 때 해당 태그의 쿼리문을 실행

<insert>

<insert id="insertMember" parameterClass="kr.or.ddit.member.vo.MemberVO">
  INSERT INTO MYMEMBER
  (MEM_ID, MEM_NAME, MEM_TEL, MEM_ADDR)
  VALUES (#memId#, #memName#, #memTel#, #memAddr#)
</insert>
  • 성공시 null 반환

<update>

<update id="updateMember"> <!-- parameterClass는 생략가능 -->
  UPDATE MYMEMBER 
  SET MEM_NAME = #memName#
  , MEM_TEL = #memTel#
  , MEM_ADDR = #memAddr#
  WHERE MEM_ID = #memId#
</update>
  • 파라미터로 MemberVO 객체가 왔지만 태그 속성의 parameterClass는 생략가능하기때문에 적어주지 않았음

<delete>

<delete id="deleteMember" parameterClass="String">
  DELETE FROM MYMEMBER WHERE MEM_ID = #memId#
</delete>

SqlMapClientFactory.java

  • 여러 dao에서 같이 쓸 수 있도록 싱글톤으로
  • MemberDaoImpl 생성자에 smc 객체 생성
public class SqlMapClientFactory {
  private static SqlMapClient smc;

  private SqlMapClientFactory() {}

public static SqlMapClient getInstance() {
  if(smc == null) {
    try {
      // 1-1. xml문서 읽어오기
      Charset charset = Charset.forName("UTF-8"); // 설정파일의 인코딩 설정
      Resources.setCharset(charset); // ibatis로 import
      Reader rd;
      rd = Resources.getResourceAsReader("SqlMapConfig.xml");

      // 1-2. 위에서 읽어온 Reader객체를 이용하여 실제 작업을 진행할 객체 생성
      smc = SqlMapClientBuilder.buildSqlMapClient(rd);

      rd.close();
    } catch (IOException e) {
      System.err.println("SqlMapClient 객체 생성 실패!!!");
      e.printStackTrace();
    } 
  }
    return smc;
  }
}

iBATIS 설명 출처

profile
갈 길이 멀다

0개의 댓글