Mybatis 01

7 minute read

Data Persistence Framework - Mybatis

Data Persistence Framework

Mybatis 설정 파일의 InputStream 읽어오기 1

// Data Persistence Framework
// => 데이터의 영속성(지속성; 등록,조회,변경,삭제)을 대신 처리해주는 프레임워크.
// 1) SQL Mapper
// - 직접 SQL 문을 작성
// - 각각의 DBMS에 최적화된 SQL을 작성할 수 있다.
// - DBMS마다 미미하게 다른 SQL을 작성해야 하는 번거로움이 있다.
// - 예) Mybatis 등
// 2) OR Mapper
// - 전용언어 및 문법(Domain-Specific Language;DSL)을 사용하여 작성
// 실행할 때 DBMS에 맞춰서 SQL을 생성하여 실행한다.
// - DBMS에 마다 SQL문을 작성할 필요가 없어 편리하다.
// - DBMS에 최적화된 SQL을 실행할 수 없다.
// 즉 DBMS의 특징을 최대로 활용할 수 없다.
// - 예) Hibernate, TopLink 등
//
// Mybatis 도입
// 1) 의존 라이브러리 추가
// - mvnrepository.com 검색하여 build.gradle 파일에 추가한다.
// - "gradle eclipse" 실행한 후 이클립스 에디터에서 프로젝트를 "refresh" 한다.
// 2) mybatis 설정 파일 준비
// - mybatis-config.xml 생성 및 편집
// 3) DB 연결 정보를 담은 프로퍼티 파일 준비
// - jdbc.properties 생성 및 편집
// 4) SQL 문장을 작성할 파일 준비
// - BoardMapper.xml 생성 및 편집
// 5) Mybatis 객체 준비
//
public class Exam0110 {

  public static void main(String[] args) throws Exception {
    // 1. mybatis 설정 파일을 읽을 InputStream 도구를 준비한다.
    // 1) 직접 파일 시스템 경로를 지정하기
    // => 단 소스 파일 경로를 지정하지 말아라.
    // => 컴파일된 후 XML 파일이 놓이는 경로를 지정해라.
    // => 자바 패키지에 작성한 일반 파일은 그대로 빌드 디렉토리에 복사된다.
    // => 예) 프로젝트폴더/bin/main/com/eomcs/mybatis/ex01/mybatis-config.xml
    //
    InputStream mybatisConfigInputStream = new FileInputStream(//
        "./bin/main/com/eomcs/mybatis/ex01/mybatis-config.xml");

    // 2. SqlSessionFactory를 만들어 줄 빌더 객체 준비
    //
    SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();

    // 3. SqlSession 객체를 만들어 줄 팩토리 객체 준비
    // => mybatis는 Builder를 이용하여 SqlSessionFactory 객체를 만든다.
    // => 이때 공장 객체를 만들 때 사용할 설정 파일을 지정한다.
    // => 설정 파일의 경로를 직접 지정하지 말고,
    // 해당 파일을 읽을 때 사용할 InputStream을 넘겨줘라.
    //
    SqlSessionFactory factory = factoryBuilder.build(mybatisConfigInputStream);

    // 4. SQL을 실행시키는 객체 준비
    // => SqlSessionFactory 객체로부터 SqlSession 객체를 얻는다.
    // => openSession()은 수동 커밋으로 SQL을 다루는 객체를 리턴한다.
    // => 자동 커밋으로 SQL을 다루고 싶다면,
    // openSession(boolean autoCommit) 메서드를 호출하라.
    //
    SqlSession sqlSession = factory.openSession();

    System.out.println("mybatis 준비 완료!");

    sqlSession.close();
  }

}

Mybatis 설정 파일의 InputStream 읽어오기 2

public class Exam0111 {

  public static void main(String[] args) throws Exception {
    // 1. mybatis 설정 파일을 읽을 InputStream 도구를 준비한다.
    // => 다음과 같이 mybatis 설정 파일의 경로를 직접 지정하면
    // 애플리케이션 배포 경로가 바뀔 때 마다
    // 소스를 변경하고 다시 컴파일 해야 하는 문제가 있다.
    // InputStream mybatisConfigInputStream = new FileInputStream(//
    // "./bin/main/com/eomcs/mybatis/ex01/mybatis-config.xml");

    // => 이를 간편하게 하기 위해 Mybatis는 도우미 객체를 제공한다.
    // => Resources 클래스의 메서드를 이용하면
    // 자바 클래스가 있는 패키지 폴더에서 mybatis 설정 파일을 찾을 수 있다.
    //
    InputStream mybatisConfigInputStream = Resources.getResourceAsStream(//
        "com/eomcs/mybatis/ex01/mybatis-config.xml");
    // => 파라미터에 mybatis 설정 파일의 경로를 지정할 때,
    // 자바 패키지 경로를 그대로 이용한다.
    // => 단 파일 경로이기 때문에 폴더와 폴더 사이를 가리킬 때
    // . 대신에 / 를 사용해야 한다.
    // => JVM은 현재 실행하는 애플리케이션의 자바 클래스 경로를 알고 있다.
    // => 주의!
    // 자바 패키지 경로에서 찾기 때문에 mybatis 설정 파일은 반드시
    // 자바 패키지 경로에 있어야 한다.
    //

    SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();

    SqlSessionFactory factory = factoryBuilder.build(mybatisConfigInputStream);

    SqlSession sqlSession = factory.openSession();

    System.out.println("mybatis 준비 완료!");

    sqlSession.close();
  }

}
  • 코드 정리
public class Exam0112 {

  public static void main(String[] args) throws Exception {

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(//
        Resources.getResourceAsStream(//
            "com/eomcs/mybatis/ex01/mybatis-config.xml"));

    SqlSession sqlSession = factory.openSession();

    System.out.println("mybatis 준비 완료!");

    sqlSession.close();
  }
}

Mybatis-config 파일

  • 01
<?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>
  <!-- mybatis 설정 파일을 작성할 때,
       자식 태그의 순서를 지켜야 한다.
       => mybatis 설정 파일 작성 규칙에 순서를 지키도록 정의되어 있다. 
   -->
  <properties resource="com/eomcs/mybatis/ex01/jdbc.properties"></properties>

  <!-- 긴 이름의 클래스명을 사용하는 대신에 짧은 이름의 별명을 사용해보자! -->
  <typeAliases>
    <!-- 주의!
      패키지를 포함한 클래스 이름은 항상 . 으로 표기해야 한다.
      / 는 파일 경로를 가리킬 때 사용한다. 
     -->
    <typeAlias type="com.eomcs.mybatis.ex01.Board" alias="Board"/>
  </typeAliases>

  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
  </environments>
  
  <mappers>
    <mapper resource="com/eomcs/mybatis/ex01/BoardMapper02.xml"/>
  </mappers>
</configuration>
  • 02
<?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>
  <!-- mybatis 설정 파일을 작성할 때,
       자식 태그의 순서를 지켜야 한다.
       => mybatis 설정 파일 작성 규칙에 순서를 지키도록 정의되어 있다. 
   -->
  <properties resource="com/eomcs/mybatis/ex01/jdbc.properties"></properties>

  <!-- 긴 이름의 클래스명을 사용하는 대신에 짧은 이름의 별명을 사용해보자! -->
  <typeAliases>
    <!-- 패키지에 소속된 전체 클래스에 대해 별명을 부여할 수 있다.-->
    <package name="com.eomcs.mybatis.ex01"/>
  </typeAliases>

  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
  </environments>
  
  <mappers>
    <mapper resource="com/eomcs/mybatis/ex01/BoardMapper02.xml"/>
  </mappers>
</configuration>
  • 03 finish
<?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>
  <!-- jdbc.properties 파일의 내용을 읽어온다.
       읽어온 정보는 ${프로퍼티명} 문법을 이용하여 그 값을 사용할 수 있다. -->
  <properties resource="com/eomcs/mybatis/ex01/jdbc.properties"></properties>

  <!-- DBMS에 연결할 때 사용할 정보를 설정한다.
       여러 개의 연결 정보를 설정해두고 그 중에 사용할 정보를 지정할 수 있다.
       default="development"의 의미는, 
       여러 연결 정보 중에서 "development"라는 연결 정보를 사용하여 실행하겠다는 의미다. -->
  <environments default="development">
    
    <!-- 각각의 연결 정보는 다음과 같이 environment 태그에 설정한다. -->   
    <environment id="development">
    
      <!-- 트랜잭션 관리 방식을 지정한다. -->
      <transactionManager type="JDBC"/>

      <!-- DB 커넥션 풀에 관련된 정보와 DB 연결 정보를 설정한다. 
           이제 개발자가 DB 커넥션 풀을 다룰 필요가 없다.
           mybatis 프레임워크에서 관리한다. -->
      <dataSource type="POOLED">
        <!-- ${위의 .properties 파일에 저장된 프로퍼티명} -->
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
  </environments>
  
  <!-- SQL문을 모아둔 파일(SQL 맵퍼 파일이라 부른다)을 지정한다.
       SQL 맵퍼 파일에 작성해 둔 SQL문을 mybatis가 사용할 것이다. -->
  <mappers>
    <!-- 맵퍼 파일의 경로를 지정할 때 classpath 경로를 사용해야 한다.
         단 패키지명을 구분할 때 '.' 대신에 '/'를 사용해야 한다. -->
    <mapper resource="com/eomcs/mybatis/ex01/BoardMapper.xml"/>
  </mappers>
</configuration>

SQL문 실행

public class Exam0120 {

  public static void main(String[] args) throws Exception {
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(//
        Resources.getResourceAsStream(//
            "com/eomcs/mybatis/ex01/mybatis-config.xml"));
    
    SqlSession sqlSession = factory.openSession();

    // SqlSession 객체를 이용하여 SQL 맵퍼 파일에 작성한 SQL 문을 실행한다.
    // => select 문장 
    //    - sqlSession.selectList() : 목록 리턴
    //    - sqlSession.selectOne() : 한 개의 결과 리턴
    // => insert 문장
    //    - sqlSession.insert() 
    // => update 문장
    //    - sqlSession.update()
    // => delete 문장
    //    - sqlSession.delete()
    // => insert/update/delete인 경우 insert()/update()/delete() 메서드 중
    //    아무거나 호출해도 된다. 
    //    하지만 일관된 유지보수를 위해 메서드를 구분하여 사용하라!
    // 
    // 메서드 사용법)
    // => 예) selectList(SQL문 식별자, 파라미터값)
    //    - SQL문 식별자 = 그룹명 + "." + SQL문장 아이디
    //      - 그룹명: <mapper namespace="그룹명">...</mapper>
    //      - SQL 문장 아이디: <select id="SQL문장 아이디">...</select>
    //    - 파라미터 값: primitive type 및 모든 자바 객체가 가능하다. 
    //                 여러 개의 값을 전달할 때는 Map에 담아 넘겨라!
    List<Board> list = 
        sqlSession.selectList("BoardMapper.selectBoard");

    for (Board board : list) {
      System.out.printf("%d, %s, %s, %s, %d\n", 
          board.getNo(), 
          board.getTitle(), 
          board.getContent(),
          board.getRegisteredDate(),
          board.getViewCount());
    }
    sqlSession.close();
  }
}

// selectList() 동작 원리
// ---------------------------------------------------------------------
// <select id="selectBoard" resultType="com.eomcs.mybatis.ex01.Board">
// select 
//   board_id,
//   title,
//   contents,
//   created_date,
//   view_count
// from x_board
// </select>
//---------------------------------------------------------------------
// => resultType 에 지정한 클래스의 인스턴스를 생성한다.
// => 컬럼 이름과 일치하는 프로퍼티를 찾아 값을 입력한다.
//    board_id      --> setBoard_id(컬럼값)
//    title         --> setTitle(컬럼값)
//    contents      --> setContents(컬럼값)
//    created_date  --> setCreated_date(컬럼값)
//    view_count    --> setView_count(컬럼값)
// => 컬럼 이름과 일치하는 프로퍼티(setter)가 없다면 
// 그 컬럼의 값은 객체에 담을 수 없다.
// => 이 예제에서 컬럼 이름과 일치하는 프로퍼티는 title 밖에 없다.

컬럼과 프러퍼티 명 일치시키기

public class Exam0121 {
  
  public static void main(String[] args) throws Exception {
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(//
        Resources.getResourceAsStream(//
            "com/eomcs/mybatis/ex01/mybatis-config.xml"));

    SqlSession sqlSession = factory.openSession();

    List<Board> list = sqlSession.selectList("BoardMapper.selectBoard2");

    for (Board board : list) {
      System.out.printf("%d, %s, %s, %s, %d\n", board.getNo(), board.getTitle(), board.getContent(),
          board.getRegisteredDate(), board.getViewCount());
    }
    sqlSession.close();
  }
}

// 컬럼 이름과 자바 객체의 프로퍼티 이름을 같게 하기
// ---------------------------------------------------------------------
// <select id="selectBoard" resultType="com.eomcs.mybatis.ex01.Board">
// select
//   board_id as no,
//   title,
//   contents as content,
//   created_date as registeredDate,
//   view_count as viewCount
// from x_board
// </select>
// ---------------------------------------------------------------------
// => 컬럼의 값을 자바 객체에 담으려면 컬럼과 같은 이름의 프로퍼티가 있어야 한다.
// => 없다면 위와 같이 프로퍼티 명을 컬럼의 별명으로 지정하라.

클래스 별명 지정하기

// mybatis 설정 파일에서 fully-qualified class name 을 사용하는 대신에
// 짧은 이름으로 대체할 수 있다.
// <typeAliases>
// <typeAlias type="com.eomcs.mybatis.ex01.Board" alias="abc"/>
// </typeAliases>
//
// 그러면 이 별명을 어디에 사용하는가?
// => SQL 맵퍼 파일에서 클래스를 지정할 때 사용한다.
// <select id="selectBoard2" resultType="abc">
//  select
//      board_id as no,
//      title,
//      contents as content,
//      created_date registeredDate,
//      view_count viewCount
//  from x_board
// </select>
//
// 참고!
// => 자바 primitive type과 wrapper 클래스, String 클래스,
//    일부 유틸리티 클래스 등에 대해서는 mybatis가 미리 별명을 지정하였다.
// => 예)
//    int       ->  _int
//    float     ->  _float
//    java.lang.Integer     -> int
//    java.lang.Float       -> float
//    java.lang.String      -> string
//    java.util.Map         -> map
//    java.util.HashMap     -> hashMap
//
//
public class Exam0210 {

  public static void main(String[] args) throws Exception {
    InputStream inputStream = Resources.getResourceAsStream( //
        "com/eomcs/mybatis/ex01/mybatis-config02.xml");
    SqlSessionFactory factory = //
        new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession sqlSession = factory.openSession();

    List<Board> list = sqlSession.selectList("BoardMapper.selectBoard");

    for (Board board : list) {
      System.out.printf("%d, %s, %s, %s, %d\n", //
          board.getNo(), //
          board.getTitle(), //
          board.getContent(), //
          board.getRegisteredDate(), //
          board.getViewCount());
    }

    sqlSession.close();
  }

}

Categories:

Updated: