위로 아래

MyBatis

--PreparedStatement
String sql = "UPDATE user SET name=?, number=? WHERE id=?";
pstmt.setInt(1, name);
pstmt.setInt(2, number);
pstmt.setInt(3, id);


--MyBtis
UPDATE user SET name=#{name}, number=#{number} WHERE id=#{id}
  1. DB를 쉽게 다루도록 도와주는 오픈소스 프레임워크
  2. JDBC 방식과 달리 xml 파일에 쿼리를 작성하게 해주어서 가독성 좋고 편하게 해주는 것.
  3. 동적 쿼리 작성 가능
  4. SQL문과 프로그램 코드의 분리
  5. SQL 실행 결과를 사용자 정의 DTO, Map 등에 매핑할 수 있다
  6. 사용 방법 순서 : 의존성 설정 -> DB 설정 -> MyBatis 설정 -> Mapper 인터페이스 작성 -> XML 작성 -> MyBatis 사용

 

장점

  1. 유연성 : SQL 쿼리를 동적으로 직접 작성할 수 있어서 유연
  2. 간결성 : 프로그래밍 언어 코드와 SQL 쿼리를 분리해서 코드를 간결하게 바꿈
  3. 성능 : 캐시 기능을 제공하여 데이터베이스 연산 속도 높임
  4. 다양한 데이터베이스에 지원

 

 


동작 순서

애플리케이션 실행 시 프로세스

  1. SqlSessionFactoryBean이 SqlSessionFactoryBuilder를 위해 SqlSessionFactory를 빌드하도록 요청
  2. 애플리케이션이 SqlSessionFactoryBuilder를 사용해 빌드된 SqlSessionFactory에서 SqlSession을 가져온다
  3. SqlSessionFactoryBuilder가 Mybatis 구성 파일의 정의에 따라 SqlSessionFactory를 생성(생성된 SqlSessionFactory는 스프링 DI 컨테이너에 의해 저장)
  4. MapperFactoryBean이 안전한 SqlSession(SqlSessionTemplate) 및 스레드 안전 매퍼 개체를 생성

 

클라이언트 요청 시 프로세스

  1. 클라이언트가 애플리케이션에 프로세스를 요청
  2. 애플리케이션이 DI 컨테이너에 주입한 mapper 객체의 메서드를 호출
  3. mapper 객체가 호출된 메서드에 해당하는 SqlSession 메서드를 호출
  4. SqlSession이 SqlSession 메서드를 호출
  5. 프록시 사용 및 스레드 안전 SqlSession이 트랜잭션에 할당된 MyBatis 표준 SqlSession을 사용
  6. SqlSessionFactory가 Mybatis 표준 SqlSession을 반환
  7. Mybatis 표준 SqlSession이 mapping 파일에서 실행할 SQL을 가져와 실행

 

 

 

 


Datasource-context.xml 설정

데이터베이스 연결

  1. MyBatis는 JDBC로 DB를 연결
  2. 스프링 설정(XML, Properties)에 DB 연결정보(DataSource) 등록
<!-- datasource-context.xml -->
<bean id="dataSourceOR" class="org.apache.commons.dbcp.BasicDataSource" 
      destroy-method="close">
  <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> 
  <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:xe"/>
  <property name="username" value="c##scott"/>   
  <property name="password" value="1234"/>
</bean>

 

 

MyBatis 설정

  1. XML 설정 파일 생성. 설정 추가
<!-- db connection info. -->
<!-- 1.mybatis f/w db connect  2. sql file location setting-->
<bean id="sqlSessionFactory" 
       class="org.mybatis.spring.SqlSessionFactoryBean" 
          lazy-init="true">
     <property name="dataSource" ref="dataSource" />
     <property name="configLocation" 
            value="/WEB-INF/spring/mybatisConfig/Mybatis-Config.xml"/>
     <property name="mapperLocations" 
           value="classpath*:**/mapper/*Mapper.xml" />
</bean>
<!-- use DAO  -->
<bean id="sqlsession" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg ref="sqlSessionFactory"/>
</bean>		
</beans>

 

전체 코드

더보기
<!-- datasource-context.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- database setting -->
	<bean id="dataSourceOR" class="org.apache.commons.dbcp.BasicDataSource" 
	          destroy-method="close">
	      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> 
	      <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:xe"/>
	      <property name="username" value="c##scott"/>   
	      <property name="password" value="1234"/>
	</bean>
	<bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
	  <constructor-arg ref="dataSourceOR"/>
	  <property name="logFormatter">
	     <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter">
	       <property name="loggingType" value="MULTI_LINE"/> 
	       <property name="sqlPrefix" value="[SQL]: "/>
	     </bean>
	  </property>
	</bean>
	
	<!-- db connection info. -->
	<!-- 1.mybatis f/w db connect  2. sql file location setting-->
	<bean id="sqlSessionFactory" 
	       class="org.mybatis.spring.SqlSessionFactoryBean" 
	          lazy-init="true">
		 <property name="dataSource" ref="dataSource" />
		 <property name="configLocation" 
		        value="/WEB-INF/spring/mybatisConfig/Mybatis-Config.xml"/>
		 <property name="mapperLocations" 
		       value="classpath*:**/mapper/*Mapper.xml" />
  	</bean>
  	<!-- use DAO  -->
  	<bean id="sqlsession" class="org.mybatis.spring.SqlSessionTemplate">
  	  <constructor-arg ref="sqlSessionFactory"/>
  	</bean>		
</beans>

 

 


pom.xml 설정

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.13</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.1.0</version>
</dependency>
더보기
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.ecom4</groupId>
	<artifactId>hi</artifactId>
	<name>springBoard</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.11</java-version>
		<org.springframework-version>4.3.4.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>
	
	<repositories>
		<repository>
		   <id>oracle</id>
		   <name>ORACLE JDBC Repository</name>
		   <url>http://mesir.googlecode.com/svn/trunk/mavenrepo</url>
		</repository>
	</repositories>
	
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<!-- db setting -->
       <dependency>
		    <groupId>org.bgee.log4jdbc-log4j2</groupId>
		    <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
		    <version>1.16</version>
		</dependency>
		 <dependency>  
            <groupId>org.lazyluke</groupId>  
             <artifactId>log4jdbc-remix</artifactId>  
              <version>0.2.7</version>  
        </dependency>  
        <dependency>  
              <groupId>org.slf4j</groupId>  
             <artifactId>slf4j-log4j12</artifactId>  
            <version>1.6.1</version>  
        </dependency>
	<!-- db setting -->
		<dependency>
		    <groupId>com.oracle.database.jdbc</groupId>
		    <artifactId>ojdbc8</artifactId>
		    <version>23.2.0.0</version>
		</dependency>
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-jdbc</artifactId>
		    <version>${org.springframework-version}</version>
		</dependency>
		<!-- connection pool -->
		<dependency>
		    <groupId>commons-dbcp</groupId>
		    <artifactId>commons-dbcp</artifactId>
		    <version>1.4</version>
		</dependency>
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis</artifactId>
		    <version>3.5.13</version>
		</dependency>
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis-spring</artifactId>
		    <version>2.1.0</version>
		</dependency>
	<!-- db setting end -->
	  <!-- lombok -->
	  <dependency>
	    <groupId>org.projectlombok</groupId>
	    <artifactId>lombok</artifactId>
	    <version>1.18.28</version>
	    <scope>provided</scope>
	  </dependency>
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>        
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

 

 

 

 


MyBatis-Config.xml 설정

직접 정의한 VO 객체로 결과를 받아오기 위해 자주 사용하는 타입의 별칭을 설정.

경로 : webapp > WEB-INF > spring > mybatisConfig > MyBatis-Config.xml

<?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>
	<settings>
		<setting name="cacheEnabled" value="false" />
		<setting name="useGeneratedKeys" value="true" />
		<setting name="defaultExecutorType" value="REUSE" />
		<setting name="jdbcTypeForNull" value="NULL" />
	</settings>
	<!-- aliaes - short name setting bvo, pvo-->
    <typeAliases>
         <typeAlias alias="hashMap" type="java.util.HashMap" />
         <typeAlias alias="map" type="java.util.Map" />
         <typeAlias alias="bvo" type="com.ecom4.hi.board.model.BoardDTO" />
     </typeAliases>
</configuration>
  1. typeAliases : 매칭할 mapper의 sql 태그의 parameter Type 별칭 설정
    1. mapper의 sql 태그의 type(parameter type)을 alias로 설정
  2. environments : DB 연결 설정
  3. mappers : mapper.xml 파일 연결 (mapper.xml 경로를 resourse로 연결)

 

 


Mapper.xml 작성

SQL 문을 담고 있는 xml 문서

경로 : src/main/resources > board > mapper > BoardSpMapper.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 namespace = "board.BoardDAO">
<select id="getArticles" resultType="bvo">
SELECT * 
FROM(SELECT ROWNUM AS rn, A.* 
FROM(SELECT bno, bref, bstep, blevel, readcount, 
subject, content, writer, regdate, ip, passwd 
FROM board 
ORDER BY bref DESC, bno, bstep) A) 
WHERE rn BETWEEN #{start} AND #{end}
</select>

<select id="getTotalCnt" resultType="int">
	SELECT COUNT(bno) FROM BOARD
</select>

<insert id="writeAction" parameterType="bvo">
	<selectKey keyProperty="nbno" resultType="int" order="BEFORE">
		SELECT NVL(MAX(bno),0)+1 AS nbno FROM board
	</selectKey>
	INSERT INTO board
		(bno, bref, bstep, blevel, readcount, 
		subject, content, writer, regdate, ip, passwd) 
	VALUES (
		#{nbno},
		<choose>
			<when test="bno>0">
				#{bno},
				#{bstep}+1,
				#{blevel}+1,
			</when>
		</choose>
		<choose>
			<when test="bno==0 and bref==0">
				#{nbno},
				0,
				0,
			</when>
		</choose>
		#{readcount}, #{subject}, #{content}, #{writer}, SYSDATE, #{ip}, #{passwd}
	)
</insert>

</mapper>
  1. namespace : 연결된 파일
  2. id : 해당 쿼리문을 사용하는 DAO의 메소드 이름
  3. parameterType
    1. 패키지 포함 클래스 풀네임으로 설정 (config 파일에서 별칭을 설정 typeAliases했다면 별칭 이용 가능)
    2. 자바 타입의 내장된 별칭 사용 가능
  4. ${   } : Statement 방식
  5. #{   } : PreparedStatement (위치홀더) 방식

 

select

<select id="getArticles" resultType="bvo">
    SELECT * 
    FROM(SELECT ROWNUM AS rn, A.* 
    FROM(SELECT bno, bref, bstep, blevel, readcount, 
    subject, content, writer, regdate, ip, passwd 
    FROM board 
    ORDER BY bref DESC, bno, bstep) A) 
    WHERE rn BETWEEN #{start} AND #{end}
</select>

<select id="getTotalCnt" resultType="int">
	SELECT COUNT(bno) FROM BOARD
</select>
  1. parameterType : 파라미터로 넣을 값의 타입
  2. resultType : 결과로 받을 값의 타입

 

 

insert, update, delete

<insert id="writeAction" parameterType="bvo">
	<selectKey keyProperty="nbno" resultType="int" order="BEFORE">
		SELECT NVL(MAX(bno),0)+1 AS nbno FROM board
	</selectKey>
	INSERT INTO board
		(bno, bref, bstep, blevel, readcount, 
		subject, content, writer, regdate, ip, passwd) 
	VALUES (
		#{nbno},
		<choose>
			<when test="bno>0">
				#{bno},
				#{bstep}+1,
				#{blevel}+1,
			</when>
		</choose>
		<choose>
			<when test="bno==0 and bref==0">
				#{nbno},
				0,
				0,
			</when>
		</choose>
		#{readcount}, #{subject}, #{content}, #{writer}, SYSDATE, #{ip}, #{passwd}
	)
</insert>
  1. parameterType : 구문에 전달될 파라미터의 패키지 경로를 포함한 전체 클래스명이나 별칭 
  2. keyProperty : 

 


동적 쿼리 태그

<insert id="writeAction" parameterType="bvo">
	<selectKey keyProperty="nbno" resultType="int" order="BEFORE">
		SELECT NVL(MAX(bno),0)+1 AS nbno FROM board
	</selectKey>
	INSERT INTO board
		(bno, bref, bstep, blevel, readcount, 
		subject, content, writer, regdate, ip, passwd) 
	VALUES (
		#{nbno},
		<choose>
			<when test="bno>0">
				#{bno},
				#{bstep}+1,
				#{blevel}+1,
			</when>
		</choose>
		<choose>
			<when test="bno==0 and bref==0">
				#{nbno},
				0,
				0,
			</when>
		</choose>
		#{readcount}, 
		#{subject},
		#{content},
		#{writer},
		SYSDATE,
		#{ip},
		#{passwd}
	)
</insert>
  1. <if>
  2. <choose>
  3. <when>
  4. <otherwise>
  5. <foreach>