[First Shop] MyBatis framework

Jason·2023년 10월 5일
0

FirstShop

목록 보기
3/5
post-thumbnail

우선 기존 프로젝트의 코드와 내역을 정리 후에 프레임워크 적용을 다룰 예정이다.

1. SQL + JDBC

SQL : Structured Query Language
Database 에 명령하는 언어이다.

JDBC : Java DataBase Connectivity
SQL 을 Java 코드 내에서 작성할 수 있도록 하는 Java 와 DB 를 연동해 주는 기술이다.

Database 는 많기 때문에 본 기술을 적용하기 위해서는 Java 와 SQL 을 연결해 줄 Driver 가 필요하고, DB 회사에서 driver 를 제공한다. (Java 가 갑, DB 회사 가 을)

다음은 간단한 상품 등록 insert 코드이다.

package com.model2.mvc.service.product.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;

import com.model2.mvc.common.Search;
import com.model2.mvc.common.util.DBUtil;
import com.model2.mvc.service.domain.Product;

public class ProductDAO {
	//Constructor
	public ProductDAO() {
	}
	//Method
	public void insertProduct(Product product) throws Exception {
		
		Connection con = DBUtil.getConnection();
		
		String sql = "INSERT INTO product VALUES (seq_product_prod_no.nextval, ?, ?, ?, ?, ?, sysdate) ";
		
		PreparedStatement pstmt = con.prepareStatement(sql);
		//prod_no = seq_product_prod_no.nextval (다음 번호 시퀀스 진행)

		pstmt.setString(1, product.getProdName()); //prod_name
		pstmt.setString(2, product.getProdDetail()); //prod_detail
		pstmt.setString(3, product.getManuDate()); //manufacture_day
		pstmt.setInt(4, product.getPrice()); // price
		pstmt.setString(5, product.getFileName()); // image_file
		// regDate 는 sysdate
		pstmt.executeUpdate();
		
		pstmt.close();
		con.close();
		
	} //end of insertProduct
} // end of class

DB 연결, SQL 작성, Object 에서 불러온 값 쿼리에 setting, sql execute DB statement, connection 닫기로 마무리 까지 순수 메서드만 약 20 줄 가량이다.

기본 CRUD 만 만들어도 class 1개 당 약 100~200 줄 가량을 차지한다.


2. MyBatis framework

DAO(Data Access Object) 에서 반복되는 jdbc, SQL 을 xml(meta-data) 기반으로 옮겨와, 코드 유지 관리를 보다 수월하게 해주고, 상황에 맞게 동적 SQL 도 구사할 수 있게 해주는 framework

MyBatis 는 xml 에 meta-data 를 기재해서 설정, Column-Object mapping 등을 한다.

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">
  						
<!--	mybatis-config.xml :: MyBatis Framework  MetaData -->
<configuration>

    <!-- FQCN(Full Qualified Class Name) Alias(별칭관리) -->
	<typeAliases>
		<typeAlias alias="user" type="com.model2.mvc.service.domain.User" />
		<typeAlias alias="product" type="com.model2.mvc.service.domain.Product" />
		<typeAlias alias="purchase" type="com.model2.mvc.service.domain.Purchase" />
		<typeAlias alias="search" type="com.model2.mvc.common.Search" />
	</typeAliases>
	
	<!-- SQL Definition :: file include -->
	<mappers>
		<mapper resource="sql/UserMapper.xml"/>
		<mapper resource="sql/ProductMapper.xml"/>
		<mapper resource="sql/PurchaseMapper.xml"/>
	</mappers>

</configuration>

해당 파일 내에 FQCN 을 alias 로 관리하고 mapper 파일 url 을 지정했다.


Mapper.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="ProductMapper">
 	
 	<!-- 각 column 과 Product bean 의 field 를 연결 -->
	<resultMap id="productSelectMap" type="product">
		<result property="prodNo" 			column="prod_no" 			jdbcType="NUMERIC"/>
		<result property="prodName"		column="prod_name" 		jdbcType="VARCHAR" />
		<result property="prodDetail" 		column="prod_detail" 		jdbcType="VARCHAR" />
		<result property="manuDate" 		column="manufacture_day" 	jdbcType="VARCHAR" />
		<result property="price" 			column="price" 				jdbcType="INTEGER" />
		<result property="fileName" 		column="image_file" 			jdbcType="VARCHAR" />
		<result property="regDate" 			column="reg_date" 			jdbcType="DATE" />
		<result property="rowNum" 		column="row_seq" 			jdbcType="NUMERIC"/>
	</resultMap>
	
	<!-- SQL : SELECT LIST -->
	<select  id="getProductList"  parameterType="search"	resultMap="productSelectMap">
	  	SELECT *
	  	FROM (	SELECT inner_table.* , ROWNUM AS row_seq
	  					FROM		(	SELECT p.prod_no, p.prod_name, p.price, p.reg_date, t.tran_status_code
										FROM product p
										LEFT OUTER JOIN transaction t
										ON p.prod_no = t.prod_no 
											<if test="searchCondition != null">
												<where>
													<if test="searchCondition == 0 and searchKeyword !='' ">
										 				p.prod_no = #{searchKeyword}
													</if>
													<if test="searchCondition == 1 and searchKeyword !='' ">
										 				p.prod_name = #{searchKeyword}
													</if>
													<if test="searchCondition == 2 and searchKeyword !='' ">
										 				p.price = #{searchKeyword}
													</if>
												</where>
											</if>
											ORDER BY prod_no ) inner_table
						WHERE ROWNUM &lt;= #{endRowNum} )
		WHERE row_seq BETWEEN #{startRowNum} AND #{endRowNum} 
	 </select>
	 	<!--  위 두번째 subQuery 의  
	 			WHERE ROWNUM &lt;= #{endRowNum} ) 는 less than
	 			WHERE ROWNUM <= #{endRowNum} ) 의미이며..
	 			< 는 keyword 로 &lt; 를	사용.
	 			
	 			<![CDATA[  ~~~  ]]> 를 이용하여 아래와 같이 사용  할 수 있다.
	 			CDATA ==> Character Data 의 의미 Java 에서 \n 같은 특수문자 처리  

				WHERE ROWNUM <![CDATA[ <=]]> #{endRowNum} )
		-->
	
	<!-- SQL : SELECT ROW Count -->	 
</mapper>

위 xml 에 서술한 SQL 과 같이 searchCondition 이 null 이 아닐 경우,
searchCondition 에 세팅한 value 에 따라 동적으로 query 가 날아가도록 만들어줄 수 있다.


이후에는 DAO 에서 직접 코드를 작성해서 진행하지 않고, 아래 코드 처럼 MyBatis 의 sqlSession 을 생성해서 method 를 호출하는 식으로 변경하였다.

그리고 Business logic 과 Persistence 계층을 더 제대로 나누어 코드 유지 관리가 쉽도록 했다.

package com.model2.mvc.service.product.impl;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import com.model2.mvc.common.Search;
import com.model2.mvc.service.domain.Product;
import com.model2.mvc.service.product.ProductDao;

//==> 제품관리 DAO CRUD 구현 중 List 예시
@Repository("productDaoImpl")
public class ProductDaoImpl implements ProductDao {
	
	///Field
	@Autowired
	@Qualifier("sqlSessionTemplate")
	private SqlSession sqlSession;
	public void setSqlSession(SqlSession sqlSession) {
		this.sqlSession = sqlSession;
	}
	
	//Constructor
	public ProductDaoImpl() {
		System.out.println(this.getClass());
	}

	@Override
	public List<Product> getProductList(Search search) throws Exception {
		return sqlSession.selectList("ProductMapper.getProductList", search);
	}
}

다음은 기존 Struts framework (.do, Action) 기반에서 Spring framework(+MVC Pattern) 로 전환 내역을 기록 예정이다.

profile
어제보다 매일 1% 성장하고 있습니다.

0개의 댓글