ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] O/R 매핑 프레임워크로 데이터 액세스 레이어 구현
    우아한 테크코스/테크코스 2020. 2. 23. 17:03
    반응형

    O/R 매핑 프레임워크

     O/R 매퍼라고 부르기도 함

     종류는 여러가지가 있는데, 대표적인 예로는 마이바티스(MyBatis)가 있음

    필요성

     데이터 액세스 레이어를 DAO로 분리하면 DB 연결과 관련된 처리를 분리해 전체 코드의 가독성이 좋아짐

     하지만, 분리한 것이므로 번거로운 DB 연결 처리가 간단해지는 것은 아님

     위의 문제를 해결하고자 시도된 방법 중 하나가 O/R 매핑 프로그램

    O/R 매핑

     O/R : 객체/관계(Object/Relation)

     O/R 매핑 : 프로그레밍 언어의 객체와 관계형 DB를 대응

     관계형 DB(RDB) : 여러 개의 테이블과 그 관계를 이용해 정보를 관리하는 DB

     임피던스 불일치 : 관계형 데이터베이스상의 표현과 객체지향 언어의 객체를 통한 표현의 차이

    > RDB : (예) 고객  / 상품 / 주문 / 주문 명세

    > Object : (예) 주문표 / 주문품

    > 가지고 있는 본질은 같지만, 표현(또는 정리해놓은 관계)이 다름

    임피던스 불일치 : 전기 공학에서 원래 사용하는 용어, RDB와 객체지향의 사고방식 차이를 전기 저항에 비유하여 부름
    - 두 장치를 접속해 전기 신호를 주고받을 때 출력하는 쪽과 입력하는 쪽의 전기 저항이 달라 전기 신호가 효율적으로 전달되지 않는 현상

    O/R 매핑 프레임워크의 역할

     임피던스 불일치를 해결하는 것 - 가장 큰 역할

     DB와의 접속을 관리 - 부차적인 기능

     정보를 캐싱해 DB 접속을 빠르게 함 - 부차적인 기능

    O/R 매핑 프레임워크를 도입하면

     O/R 매핑 프레임워크가 등장하기 전에는 JDBC를 이용해 DB에서 정보를 구해 그 정보를 자바 객체로 다시 조립하는 단순한 코드를 대량으로 작성해야 했고, 사람이 수작업으로 작성하려면 버그가 발생할 위험이 있었음

     O/R 매핑 프레임워크를 이용하면 이런 위험을 피하고, 개발 작업을 효율적으로 할 수 있음

    O/R 매핑 프레임워크가 제공하는 기능(예 - 아이바티스(iBATIS))

    아이바티스가 제공하는 기능

     애플리케이션 > Dao 프레임워크 > 데이터 매퍼 > 데이터 베이스

    - Dao 프레임워크 + 데이터 매퍼

    - Dao 정의 파일(dao.xml) 관리

    - SQL 맵 설정 파일(sqlMapConfig.xml) 관리

    - SQL 맵 파일(XXX_sqlMap.xml) 관리

    데이터 매퍼와 SQL 맵 파일을 이용한 O/R 매핑 처리

     데이터 매퍼와 데이터 매퍼의 정의 파일인 SQL 맵 설정파일, SQL 맵 파일은 아이바티스의 근간을 이루는 요소로, 이것들을 통해 O/R 매핑 처리가 구현

     아이바티스 뿐만 아니라 대부분의 O/R 매핑 프레임워크는 DB와 객체의 대응을 특정 형태의 정의 파일에 기술함

     아이바티스 - SQL맵파일.xml : DB와 객체의 대응, DB 연결에 사용하는 SQL문을 기술하는 것이 특징

     예시 - SQL 맵 파일(PRODUCT_ITEM_SqlMap.xml)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL MAP 2.0//EN"
      "http://ibatis.apache.org/dtd/sql-map-2.dtd" >
      
    <sqlMap namespace="PRODUCT_ITEM" >
      <resultMap id="prodcutItemResult"
          class="jamie.webtext.pentomino.model.ProductItem" >
          <result column="ITEM_ID" property="itemId" jdbcType="VARCHAR" />
          <result column="ITEM_NAME" property="itemName" jdbcType="VARCHAR" />
          <result column="PRICE" property="price" jdbcType="INTEGER" />
      </resultMap>
      
      <select id="selectAll" resultMap="productItemResult"
        resultClass="jamie.webtext.pentomino.model.ProductItem">
        select ITEM_ID, ITEM_NAME, PRICE from PRODUCT_ITEM
      </select>
    </sqlMap>

     크게 나눠서 ResultMap(리절트맵)과 SQL문의 정의가 지정되어 있음

     리절트맵 : SELECT문을 통해 DB로부터 가져온 결과와 자바 객체의 프로퍼티 대응을 정의

     SQL문 : 아이바티스에서 실행하는 SQL을 정의 - SQL을 ㅁ여시적으로 기술함으로써 상세한 요건에 대응할 수 있음

     

     O/R 매퍼 중에는 SQL을 정의하지 않아도 매핑 정의를 바탕으로 SQL을 자동으로 조립해주는 것도 있음

     장점 : 편함

     단점 : DB에 어떤 SQL을 실행할지 세밀하게 지정할 수 없음

     

     일반적으로는 테이블별로 SQL 맵 파일을 나눠서 정리

     이러한 SQL 맵 파일을 한데 묶어 DB에 대한 연결 설정 등 아이바티스 전체에 관한 설정을 기술하는 것이 SQL 맵 설정 파일

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE SqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
     "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
     
    <sqlMapConfig>
      <!-- DB 접속 설정 -->
      <transactionManager type="JDBC">
        <dataSource type="JNDI">
          <property name="DataSource" value="java:comp/env/jdbc/pentominoDB" />
        </dataSource>
      </transactionManager>
      
      <!-- SqlMap 파일 참조 -->
      <sqlMap resource="sqlmap?PRODUCT_ITEM_Sql_Map.xml" />
    
    </sqlMapConfig>

     DB에 대한 연결 설정은 직접 DB서버의 호스트명이나 ID, PW같은 연결 정보를 지정해 직접 연결하게 하는 방법도 있지만, 여기서는 애플리케이션 서버가 DB에 대한 접속을 관리하는 것을 전제로 삼음 = 위처럼 JNDI를 사용해 DataSource를 경유해 연결을 획득하도록 정의

     SQL 맵 파일이 여러 개일 경우 위같이 sqlMap 요소를 기술해 나감

    Dao 프레임워크를 이용한 DAO의 작성(아이바티스가 제공하는 Dao 프레임워크 이용)

     아이바티스를 이용한 DAO를 위한 인터페이스

    public interface ProductItemDao extends Dao {
      /**
       * 상품 목록을 취득한다.<br />
       * 
       * @return 상품의 목록
       */
     public List<ProductItem> selectAll() throws SQLException;
    }

     아이바티스를 이용한 DAO 구현 클래스

    - 실제 처리는 작성 한 인터페이스에 대한 구현 클래스로 작성하지만, Dao 프레임워크의 기능을 이용하면 코드를 크게 단순화할 수 있음

    - 아래 예에서는 실질적으로 DB에 접속하는 코드는 단 한 줄 뿐임

    - Dao 프레임워크에서 제공하는 SqlMapExecutor의 queryForList를 호출했는데, 인수로 전달한 selectAll이라는 문자열이 SQL 맵 파일에 기술한 SQL문의 ID를 나타냄

     - SQL문의 ID를 지정해 호출할 뿐이며, 그 다음에는 아이바티스가 SQL의 발행과 자바 객체에 대한 매핑을 자동으로 실행

     - 실행하는 SQL이나 테이블의 구성이 변경되더라도 소스코드가 아닌 SQL 맵파일만 바꾸면 되므로 변경이 쉬움

    public class ProductItemDaoImpl extends SqlMapDaoTemplate implements ProductItemDao {
      
      public ProductItemDaoImpl(DaoManager daoManager) {
        super(daoManager);
      }
      
      @Override
      public List<ProductItem> selectAll() throws SQLException {
        // 실질적으로 DB에 접속하는 코드
        return getSqlMapExecutor().queryForList("selectAll");
      }
    }

     DAO 정의 파일(dao.xml)

    - DAO 정의 파일에 DAO를 등록하면 DAO를 호출할 수 있음

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE daoConfig PUBLIC "-//iBATIS.com//DTO DAO Configuration 2.0//EN"
      "http://www.ibatis.com/dtd/dao-2.dtd">
      
    <daoConfig>
      <context>
        <!-- SQL 맵 설정 파일에 대한 참조를 기술-->
        <transactionManager type="SQLMAP">
          <property name="SqlMapConfigResource" value="sqlMapConfig.xml" />
        </transactionManager>
        
        <!-- 준비한 DAO별로 dao요소를 기술하고 인터페이스와 구현 클래스의 이름을 등록 (여러개인 경우 수만큼 기술) -->
        <dao interface="jamie.webtext.pentomino.dao.ProductItemDao" implementation="jamie.webtext.pentomino.dao.impl.ProductItemDaoImpl"/>
      </context>
      
    </daoConfig>

     아이바티스를 이용한 getProductList 메서드

    - DaoManagerBuilder를 이용해 앞에서 dao.xml에 등록한 ProductItemDao의 객체를 취득

    - Dao를 취득하면 selectAll 메서드를 호출하여 DB에 SQL을 실행해 그 결과를 ProductItem 객체에 저장하고 리스트를 되돌려주는 것까지 모두 Dao가 처리함 - 아래 실질적 한 줄

    public List<ProductItem> getProductList() {
      // DAO 취득
      ProductItemDao productItemDao;
      try {
        Reader reader = Resource.getResourceAsReader("dao.xml");
        DaoManager daoManager = DaoManagerBuilder.buildDaoManager(reader);
        productItemDao = (ProductItemDao) daoManager.getDao(ProductItemDao.class);
      } catch (IOException ex) {
        throw new AppException(ex);
      }
      
      // 상품 정보 목록의 취득
      List<ProductItem> result;
      try {
          // 실질적으론 이 한 줄이 DB에 대한 연결 처리를 모두 끝내는 것
          result = productItemDao.selectAll();
      } catch (SQLException ex) {
          throw new AppException(ex);
      }
      
      return result;
    }

     사용하는 테이블이 늘어나고 복잡한 질의를 하게 되면 O/R 매핑 프레임워크의 효과를 더욱 확실히 알 수 있음

    반응형

    댓글

Designed by Tistory.