본문 바로가기
국비학원

[국비지원] KH 정보교육원 91일차

by 도전하는 개발자 2022. 8. 11.

Mapper Interface를 등록할 때 하나하나 등록하면 나중에 인터페이스가 많아지면 귀찮다.
패키지를 이용해 한번에 등록하는 방법을 알아보자!!!


---

이번엔 mybatis-config.xml에 등록하지 않고 하는 방법을 알아보자

 

import org.apache.ibatis.annotations.Select;

// MyBaits의 Mapper Interface
public interface TimeMapper {
	
	@Select("SELECT to_char(current_date, 'yyyy/MM/dd HH24:mi:ss') FROM dual")
	public abstract String getCurrentTime1();

} // end interface

TimeMapper.java

 

@Log4j2
@NoArgsConstructor

@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BoardMapperWithoutConfigXMLTests {
   
   // 후에라도 동적으로 Mapper Interface or XML 파일등을 등록할 때 필요.
   private Configuration myBatisConfig;
   
   private SqlSessionFactory sqlSessionFactory;
   
   
   // 선처리작업(1회성)으로 마이바티스의 설정을 동적으로 생성(XML설정파일없이...)
   @BeforeAll
   void beforeAll() {
      log.trace("beforeAll() invoked.");
      
      // ------------------------------------
      // Step1. Connection Pool을 제공하는 DataSource(javax.sql.DataSource 규격을 준수하는)를 생성
      // ------------------------------------
      HikariConfig hikariConfig = new HikariConfig();
      
      // 1. 기본적인 JDBC Connection 생성을 위한 연결정보 4가지 설정
      hikariConfig.setJdbcUrl("jdbc:log4jdbc:oracle:thin:@db20220510181503_high?TNS_ADMIN=C:/opt/OracleCloudWallet/ATP");
      hikariConfig.setDriverClassName("net.sf.log4jdbc.sql.jdbcapi.DriverSpy");
      hikariConfig.setUsername("ADMIN");
      hikariConfig.setPassword("Oracle12345678");
      
      // 2. Connection Pool과 관련된 설정
      hikariConfig.setMaximumPoolSize(7);
      hikariConfig.setMinimumIdle(3);
      hikariConfig.setConnectionTimeout(1000 * 3);
      hikariConfig.setConnectionTestQuery("SELECT 1 FROM dual");
      
      log.info("\t+ 1. hikariConfig: {}", hikariConfig);

      // ------------------------------------
      // Step2. Hikari DataSource 생성
      // ------------------------------------
      HikariDataSource dataSource = new HikariDataSource(hikariConfig);   // 자원객체임
      
      Objects.requireNonNull(dataSource);
      log.info("\t+ 2. dataSource: {}, type: {}", dataSource, dataSource.getClass().getName());

      // ------------------------------------
      // Step3. TX 관리자 생성
      // ------------------------------------
      TransactionFactory txFactory = new JdbcTransactionFactory();
      assertNotNull(txFactory);

      // ------------------------------------
      // Step4. 실행환경(Environment) 1개 생성
      // ------------------------------------
      Environment env = new Environment("development", txFactory, dataSource);
      assertNotNull(env);

      // ------------------------------------
      // Step5. Configuration 생성
      // ------------------------------------
      Configuration conf = new Configuration(env);
      assertNotNull(conf);

      // ------------------------------------
      // Step6. Configuration 에 Mapper Interface와 Mapper XML파일 등록
      // ------------------------------------
      conf.addMappers("org.zerock.myapp.mapper");
            
      this.myBatisConfig = conf;

      // ------------------------------------
      // Step7. SqlSessionFactory 생성
      // ------------------------------------
      SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
      this.sqlSessionFactory = builder.build(myBatisConfig);
   } // beforeAll
   
   
//   @Disabled
   @Test
   @Order(1)
   @DisplayName("1. testGetCurrentTime1")
   @Timeout(value=3, unit=TimeUnit.SECONDS)
   void testGetCurrentTime1() {
      log.trace("testGetCurrentTime1() invoked.");
      
//      @Cleanup
      SqlSession sqlSession = this.sqlSessionFactory.openSession();
      
      try (sqlSession) {
         // Dynamic Proxy API로, 지정된 Mapper Interface에 대한 구현객체 획득
         TimeMapper mapper = sqlSession.<TimeMapper>getMapper(TimeMapper.class);
         
         Objects.requireNonNull(mapper);
         log.info("\t+ mapper: {}", mapper);
         
         String now = mapper.getCurrentTime1();
         log.info("\t+ now: {}", now);
      } // try-with-resources
   } // testGetCurrentTime1
   
   
//  @Disabled
  @Test
  @Order(2)
  @DisplayName("2. testSelectAllBoards")
  @Timeout(unit = TimeUnit.SECONDS, value = 30)
  void testSelectAllBoards() {
     log.trace("testSelectAllBoards() invoked.");
 
    @Cleanup
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
   
    BoardMapper mapper = sqlSession.<BoardMapper>getMapper(BoardMapper.class);
    
    List<BoardVO> list = mapper.selectAllBoards(200, "0");
//    log.info("\t+ list: {}", list);
    list.forEach(log::info);
  } // testSelectAllBoards
  
  
  @Test
  @Order(3)
  @DisplayName("3. testSelectBoard")
  @Timeout(value = 30, unit = TimeUnit.SECONDS)
  void testSelectBoard() {
     log.trace("testSelectBoard() invoked.");
     
     SqlSession sqlSession = this.sqlSessionFactory.openSession();
     
     try(sqlSession) {        
        BoardMapper mapper = sqlSession.<BoardMapper>getMapper(BoardMapper.class);
        BoardVO board = mapper.selectBoard(77);
        
        Objects.requireNonNull(board);
        log.info("\t+ board : {}", board);
     } // try-with-resources
  } // testSelectBoard
  
} // end class

BoardMapperWithoutConfigXMLTests.java


---

이제 마이바티스의 가장 강력한 기능중 하나인 동적 SQL을 배우자 이걸 배우면 마이바티스의 거의 모든 용법을 배우게 된다. 이후에 스프링 프레임워크와 연동하면 새로운 용법이 하나 더 있지만 그건 그때 배우자

src/main/resources에 Board2Mapper.xml를 만들어주자

 

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

<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<!-- 여러개의 Mapper XML 파일이 존재할 때, 
    각 Mapper XML 파일의 최상위 태그의 namespace 속성 값은 고유해야함 (충돌이 없어야함)
    관례상 파일명과 동일하게 설정해준다. -->
<mapper namespace="mappers.Board2Mapper">

    <!-- 동적 SQL 문장 저장 -->
    <select 
        id="findBoardsByBno"
        resultType="org.zerock.myapp.domain.BoardVO">
        
        SELECT *
        FROM tbl_board
     
        <!-- 검색조건1: 특정 BNO에 해당하는 게시글 하나 조회 -->
        <if test="bno != null">
            WHERE bno = #{bno}
        </if>    
    </select>

    <select 
        id="findBoardsByTitle"
        resultType="org.zerock.myapp.domain.BoardVO">
        SELECT *
        FROM tbl_board

        <!-- 검색조건2 :  특정 검색어를 포함하고 있는 제목을 가지는 모든 게시글 조회 -->
        <where>
            <if test="title != null">
                title LIKE '%'||#{title}||'%'
            </if>
        </where>
    </select>

    <select 
        id="findBoardsByWriter"
        resultType="org.zerock.myapp.domain.BoardVO">
        SELECT *
        FROM tbl_board

        <trim prefix="WHERE">
            <if test="writer != null">
                writer LIKE '%'||#{writer}||'%'
            </if>
        </trim>
    </select>

    <select 
        id="findBoardsByBnoAndTitle"
        resultType="org.zerock.myapp.domain.BoardVO">
        SELECT *
        FROM tbl_board
        <trim prefix="WHERE" prefixOverrides="AND | OR">
            <if test="bno != null">
                bno > #{bno}
            </if>

            <if test="title != null">
                title LIKE '%'||#{title}||'%'
            </if>
        </trim>
    </select>

    <select 
        id="findBoardsByBnoOrTitle"
        resultType="org.zerock.myapp.domain.BoardVO">
        SELECT *
        FROM tbl_board
        
        <where>
            <choose>
                <when test="bno != null">
                    bno > #{bno}
                </when>

                <when test="title != null">
                    OR title LIKE '%'||#{title}||'5'
                </when>

                <otherwise>
                    bno > 0
                </otherwise>
            </choose>
        </where>
    </select>

    <select 
        id="findBoardsByBnos"
        resultType="org.zerock.myapp.domain.BoardVO">
    SELECT *
    FROM tbl_board
    
    <where>
        bno IN

        <foreach collection="list" open="" index="" close="" item="" separator="" ></foreach>
    </where>
    
    </select>

</mapper>

Board2Mapper.xml