티스토리 뷰

 

[ 1. SqlSessionFactoryBuilder / SqlSessionFactory ] (*)

 

import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;

import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;

@Log4j2
@NoArgsConstructor

@TestInstance(Lifecycle.PER_CLASS)

// @TestMethodOrder로 테스트 메소드 실행순서를 어떻게 할 것인지 정하는데,
// 주로 OrderAnnotation을 지정하여 @Order로 순서를 지정하게 한다.
@TestMethodOrder(OrderAnnotation.class)
public class SqlSessionFactoryTests {
	
	// sqlSessionFactory를 건설하는 건설사
	private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	private SqlSessionFactory sqlSessionFactory;
	
	// ==============================================
	
	// @BeforeAll는 사전처리로 단 1번만 수행된다.
	@BeforeAll
	void beforeAll() throws IOException {
		
		log.trace("beforeAll() invoked.");
		
		// mybatis의 설정파일 경로
		String config = "mybatis-config.xml";
		
		@Cleanup
		InputStream is = Resources.getResourceAsStream(config);
		
		// sqlSessionFactory 생성
		this.sqlSessionFactory = this.sqlSessionFactoryBuilder.build(is);
		assertNotNull(this.sqlSessionFactory);
		log.info("\t + this.sqlSessionFactory : {}", this.sqlSessionFactory );
		
		// sqlSessionFactoryBuilder 생성
		// this.sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
		// Objects.requireNonNull(this.sqlSessionFactoryBuilder);
		// log.info("\t + this.sqlSessionFactoryBuilder : {}", this.sqlSessionFactoryBuilder);
		
	} // beforeAll
	
	// ==============================================
	
	// @Disabled
	@Test
	@Order(1)
	@DisplayName("1. getSqlSession")
	@Timeout(value=3000, unit=TimeUnit.MILLISECONDS)
	void getSqlSession() throws Exception {
		
		log.trace("getSqlSession() invoked.");
		
		// ==============================================
		
		// sqlSessionFactory 객체로부터 SqlSession을 얻어내자!!
		// sqlSession 객체를 다 사용하고 나면, 반드시 자원해제를 해줘야 한다.
		
		// @Cleanup // 자원해제
		SqlSession sqlSession = this.sqlSessionFactory.openSession();
		Objects.requireNonNull(sqlSession);
		log.info("\t + sqlSession : {}", sqlSession);
		
		// SQL 문장 처리를 프레임워크에 의뢰
		try ( sqlSession ){
			;;
		} // try - with - resources
		
		// ==============================================
		
		// SQL 연결을 얻어낸다.
		// Connection conn = sqlSession.getConnection();
		// assert conn != null;
		// log.info("\t + conn : {}", conn);
		
		// ==============================================
		
	} // contextLoads
	
} // end class

[ 2. MyBatis 규격 - SqlSessionFactoryBuilder / SqlSessionFactory ] (*****)

 

[ 2 - 1. myBatis-config.xml : myBatis 환경설정 파일 만들기 ]

 

<?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>
    
    <!-- 서비스 환경 -->
    <environments default="production">

        <environment id="development">
            <transactionManager type="JDBC"/>
    
            <!-- dataSource는 Connection pool 제공해 준다. -->
            <dataSource type="UNPOOLED">
                <!-- JDBC Driver spy 적용X ver. -->
                <!-- <property name="driver" value="oracle.jdbc.OracleDriver"/> -->
                <!-- <property name="url" value="jdbc:oracle:thin:@db000000_high?TNS_ADMIN=C:/opt/OracleCloudWallet/ATP"/> -->
        
                <!-- JDBC Driver spy 적용 ver. -->
                <property name="driver" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"/>
                <property name="url" value="jdbc:log4jdbc:oracle:thin:@db000000_high?TNS_ADMIN=C:/opt/OracleCloudWallet/ATP"/>
        
                <property name="username" value="ADMIN"/>
                <property name="password" value="Oracle000000"/>
        
                <!-- <property name="defaultTransactionIsolationLevel" value="" /> -->
                <!-- <property name="defaultNetworkTimeout" value="1000" /> -->
                <property name="driver.encoding" value="utf8" />
            </dataSource>
        </environment>
    
    
        <environment id="production">
            <transactionManager type="JDBC"/>
    
            <dataSource type="POOLED">
                <!-- JDBC Driver spy 적용X ver. -->
                <!-- <property name="driver" value="oracle.jdbc.OracleDriver"/> -->
                <!-- <property name="url" value="jdbc:oracle:thin:@db000000_high?TNS_ADMIN=C:/opt/OracleCloudWallet/ATP"/> -->
        
                <!-- JDBC Driver spy 적용 ver. -->
                <property name="driver" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"/>
                <property name="url" value="jdbc:log4jdbc:oracle:thin:@db000000_high?TNS_ADMIN=C:/opt/OracleCloudWallet/ATP"/>
        
                <property name="username" value="ADMIN"/>
                <property name="password" value="Oracle0000000"/>
        
                <property name="poolMaximumActiveConnections" value="10" />
                <property name="poolMaximumIdleConnections" value="3" />
                <property name="poolTimeToWait" value="20000" />
                <property name="poolPingQuery" value="SELECT 1 FROM dual" />
                <property name="poolPingEnabled" value="true" />
                <property name="poolPingConnectionsNotUsedFor" value="60000" />
        
                <property name="driver.encoding" value="utf8" />
          </dataSource>
          
        </environment>
    
    </environments>

    <!-- 관리할 Mapper 파일 작성해 주기 (***) -->
    <!-- Mapper 파일은 여러개일 수 있다. -->
    <mappers>
        <mapper resource="BoardMapper.xml" />
    </mappers>

</configuration>

 

[ 2 - 2. BoardMapper.xml : sql문장을 지니고 있는 파일 설정 ]

 

<?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 namespace="BoardMapper">

    <!-- CRUD의 기본적인 태그를 지니고 있다. -->

    <!-- 태그의 id는 주로 실행시킨 메소드의 이름을 그대로 사용한다. (맘대로 작성해도 ok) -->
    <!-- id의 값은 유니크해야 한다. -->

    <!-- resulType은 반환될 구체타입을 지정해 주면 된다. : List타입을 반환하지만 실제로는 List<BoardVO>이기에 BoardVO의 FQCN을 지정해주면 된다. -->
    <!-- 즉, List<E>를 반환한다면 resulType에 <E>를 지정해 주면 된다. -->

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

    <!-- <insert id=""></insert> -->

    <!-- <update id=""></update> -->

    <!-- <delete id=""></delete> -->

</mapper>

 

[ 2 - 3. VO : 테이블에 맞게 VO 만들기 ]

 

package org.zerock.myapp.domain;

import java.sql.Timestamp;

import lombok.Value;

@Value // VO 객체는 Value, DTO는 @data
public class BoardVO {
	
	// null도 포함되어야 하기 때문에 참조타입이어야 한다.
	// 기본타입(ex. int)은 참조타입(ex. Integer)과 다르게 NULL을 받아들일 수 없다.
	private Integer bno;
	private String title;
	private String content;
	private String writer;
	
	private Timestamp insert_ts;
	private Timestamp update_ts;
	
	// Timestamp는 오류가 날 수 있는데, 그렇다면 Date를 사용하자
	// private Date INSERT_TS;
	// private Date UPDATE_TS;
	
	// private LocalDateTime INSERT_TS;
	// private LocalDateTime UPDATE_TS;

} // end class

 

[ 2 - 4. SqlSessionTests.java : 실행하기 ]

 

import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.Timeout;
import org.zerock.myapp.domain.BoardVO;

import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;

@Log4j2
@NoArgsConstructor

@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class SqlSessionTests {
	
	private SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
	private SqlSessionFactory sqlSessionFactory;
	
	// ======================================================
	// 1. 사전처리로 마이바틱스 설정을 기반으로 SqlSessionFactory 객체 생성 @BeforeAll
	// ======================================================
	@BeforeAll
	void beforeAll() throws IOException {
		
		log.trace("beforeAll() invoked.");
		
		// 마이바틱스 설정 파일
		String myBatisConfigXml = "mybatis-config.xml";
		
		@Cleanup
		InputStream is = Resources.getResourceAsStream(myBatisConfigXml);
		Objects.requireNonNull(is);
		
		this.sqlSessionFactory = builder.build(is);
		
	} // beforeAll
	
	// ======================================================
	// 2. SQL을 실행할 메소드 생성 - selectAllBoards ( SELECT문 )
	// ======================================================
	// @Disabled
	@Test
	@Order(1)
	@DisplayName("2. selectAllBoards")
	@Timeout(value=10, unit=TimeUnit.SECONDS)
	void selectAllBoards() {
		
		log.trace("selectAllBoards() invoked.");
		
		// SqlSessionFactory 객체에서 SqlSession 얻기
		SqlSession sqlSession = this.sqlSessionFactory.openSession();
		
		// ======================================================
		// 2 - 1. SQL 문장 처리를 프레임워크에 의뢰
		// ======================================================
		try ( sqlSession; ) {
			
			// ====================================
			// 아래의 2가지가 많이 사용된다.
			
			// 1. 반환되는 결과가 1개일때
			// sqlSession.selectOne(sql);
			
			// 2. 반환되는 결과가 0개 이상일때
			// sqlSession.selectList(sql);
			// ====================================
			
			// ==================================================================
			// String sql = "SELECT * FROM tbl_board"; <--- Mapper.xml로 이동
			// 마이바틱스에서 실행시킬 sql문장은 Mapper.xml에서 보관한다.
			// ==================================================================
			// 마이바틱스가 요구하는 규칙 ( 수행시킬 SQL문장을 지정하는 방식 ) :
			// 1) 각 SQL Mapper XML 파일 안의 namespace 속성마다 고유한 값을 가져야 한다.
			// 2) 각 SQL Mapper XML 파일 안에 저장된 각 SQL 태그마다 고유한 id값을 가져야 한다.
			// + 주로 id값은 일반적으로 SQL을 수행할 메소드의 이름과 동일하게 작성한다.
			// + 하지만 필수요구사항은 아니기에 개발자가 원하는대로 id값을 작성해도 된다. ( 단, 고유해야 한다. )
			// ==================================================================
			
			// 이 규격을 지켜야 한다.
			String namespace ="BoardMapper";
			String sqlId = "selectAllBoards";
			String sql = namespace + "." + sqlId;	// Unique Identifier
			
			List<BoardVO> list = sqlSession.selectList(sql);
			assertNotNull(list);
			
			// 마이바틱스에서 실행시킬 sql문장은 Mapper.xml에서 보관한다.
			list.forEach(log::info);
			
		} // try - with - resources
		
		// ======================================================
		
	} // selectAllBoards

} // end class

 

 

 

728x90
댓글
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
최근에 올라온 글
Total
Today
Yesterday
공지사항