ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링(Spring) ORM : MyBatis 예제
    Spring/컨셉 2018. 9. 7. 10:11

    ORM : Object Relational Mapping Framework로 객체 관계 매핑을 좀더 쉽게 돕는 프레임워크이다.
    서블릿으로 작성할 때에는 DAO 코드에 쿼리문을 넣고 그에 해당하는 정보를 가져와 멤버에 대해 하나하나 rs.getxx() 메소드 등으로 값을 직접 제어했다면, MyBatis에서는 데이터 타입에 관계 없이 멤버명만으로 값 설정이 가능하다. 이를 위해서 환경 설정이 만만치 않다. 실무에서는 이러한 설정이 잘 되어 있는 프로젝트를 하나 가지고 복사해 사용하면 된다. MyBatis 연동 방법 포스팅

    연동에 필수적인 세가지가 있는데
     1) Connection Pool
     2) MyBatis
     3) Ojdbc6.jar 파일이다.

    1번은 commons-dbcp(dbcp가 Database Connection Pool의 약어)를 사용했고, 3번은 데이터베이스 연동시 적용시켰다. 이전 포스팅 참조
    http://blog.naver.com/p952973/220980500467

    pom.xml - Dependencies 탭에서 mybatis-spring 검색 후 추가

    mybatis 검색해 추가

    spring-jdbc 검색해 추가

    (DB 연동 위해 필요)

    aspectjweaver 검색해 추가

    Spring AOP 사용하기 위함. 특정 이벤트 발생했을 때 처리를 용이하게 돕는다(Git의 hook / Trigger와 비슷한 컨셉)



    rootContext.xml(데이터베이스 관련 정보 갖는 xml 파일) 에 다음과 같이 sqlSessionFactory, sqlSessionTemplate Bean 객체 추가. 간단히 설명하자면

    SqlSessionFactoryBean : Connection 얻어오는 역할 (getConnection() 메소드 등)
    SqlSessionTemplate : select, update, insert, delete 등 쿼리문 작성의 간편화 돕는 클래스

    sqlSessionTemplate의 경우 property가 아닌 consrtuctor-arg를 넣고 있는데 이는 생성자 파라미터를 의미한다. 해당 클래스를 따라가 보면

    boardContext.xml 파일에 BoardVO 객체와 관련된 설정을 지정하도록 한다.
    bean 통해 bean Container에 들어갈 객체 생성한다.
    id : 객체명
    class : 객체 타입
    property : 객체 멤버변수의 setter 역할을 수행한다. 멤버변수가 String을 포함한 primitive 타입의 변수인 경우 value, 레퍼런스 객체인 경우 ref 속성을 사용해 값을 지정한다. setter가 각각의 Service, Biz, 파일에 있어야 한다(서블릿에서는 생성자였다)


    package com.blog.naver.board.service;
    
    import com.blog.naver.board.biz.BoardBiz;
    import com.blog.naver.board.vo.BoardListVO;
    import com.blog.naver.board.vo.BoardSearchVO;
    import com.blog.naver.board.vo.BoardVO;
    
    public class BoardServiceImpl implements BoardService{
    
    	private BoardBiz boardBiz;
    	
    	public void setBoardBiz(BoardBiz boardBiz) {
    		this.boardBiz = boardBiz;
    	}
    
    	@Override
    	public BoardListVO getAllArticles(BoardSearchVO boardSearchVO) {
    		return boardBiz.getAllArticles(boardSearchVO);
    	}
    
    	@Override
    	public BoardVO getOneBoard(int boardId) {
    		return boardBiz.getOneBoard(boardId);
    	}
    
    	@Override
    	public boolean addOneBoard(BoardVO board) {
    		return boardBiz.addOneBoard(board);
    	}
    	
    	@Override
    	public boolean removeOneBoard(int boardId) {
    		return boardBiz.removeOneBoard(boardId);
    	}
    	
    }
    
    

    ※ BoardServiceImpl 클래스. 생성자 대신 Setter를 추가해줘야 MyBatis를 사용할 수 있다!

    ※ 기존 코드에서는 dataSource를 Dao 코드의 private 멤버로 두고 property로 설정하는 방식을 사용했다. 이제  sqlSessionTemplate 객체를 property로 설정한다. Connection Pool에 대한 정보를 생성자 매개변수로 갖고 있기 때문에 Dao 코드에 더이상 dataSource 멤버가 있을 필요가 없다.

    - dao 패키지 하위에 sql 패키지 만들고 sql 패키지에서 마우스 오른쪽 버튼 - New - File 클릭
    - boardDaoSql.xml 로 파일명 등록 후 Finish(필자는 만들어놓았기 때문에 Finish 버튼이 비활성화)

    Mapper 생성
    Sql이 파일명에 붙은 것을 봐도 알 수 있듯이 커맨드 객체와 관련된 쿼리문들을 작성하는 xml 파일을 생성한다. 해당 xml 파일을 등록할 인터페이스, 메소드, 매개변수, 리턴 타입 등 각종 정보를 매핑시키기 위한 정보를 담고 있다. 이를 Mapper라 하고, 위의 코드는 따로 지원을 해주지 않아 직접 입력해야 한다. (스프링에서는 Spring-hibernate를 지원하고, Spring-mybatis는  미지원하고 있다)
    코드는 다음과 같다




    <mapper namespace="BoardDao"> 
    	<!-- 쿼리문 결과 타입
    		? 대신에 #{변수명} 사용.
    	 -->
    	
    	<select id="getAllArticles" resultType="BoardVO">
    		<!-- 로그 쿼리문 찾을 때 찾기 용이하도록 하기 위한 주석 -->
    		SELECT	/*[BoardDao][getAllArticles]*/
    		<!-- rs.setString, rs.getInt 필요한 경우 BoardVO 객체에 해준다. -->
    				BOARD_ID boardId
    				, SUBJECT subject
    				, CONTENT content
    				, WRITER writer
    				, WRITE_DATE writeDate
    				, LIKE_COUNT likeCount
    				, IP ip
    				, PST post
    		FROM	BOARD
    	</select>
    	
    	<insert id="insertOneArticle" 
    			parameterType="BoardVO">
    		 INSERT	INTO	BOARD	/*[BoardDao][insertOneArticle]*/
    		 						(
    		 							BOARD_ID 
    		 							, SUBJECT 
    		 							, CONTENT 
    		 							, WRITER 
    		 							, WRITE_DATE
    		 							, LIKE_COUNT
    		 							, IP
    		 							, PST
    		 						)
    		 VALUES					(
    		 							BOARD_ID_SEQ.NEXTVAL
    		 							, #{subject}
    		 							, #{content}
    		 							, #{writer}
    		 							, SYSDATE
    		 							, 0
    		 							, #{ip}
    		 							, #{post}
    		 						)
    	</insert>
    	
    	<select id="selectOneArticle"
    			 parameterType="_int"
    			 resultType="BoardVO">
    		SELECT	/*[BoardDao][getOneArticles]*/
    				BOARD_ID boardId
    				, SUBJECT subject
    				, CONTENT content
    				, WRITER writer
    				, WRITE_DATE writeDate
    				, LIKE_COUNT likeCount
    				, IP ip
    				, PST post
    		FROM	BOARD
    		WHERE	BOARD_ID = #{boardId} <!-- board 객체의 boardId 아니고 매개변수명이다~ -->
    	</select>
    	
    	<delete id="deleteOneArticle"
    			parameterType="_int">
    			DELETE	/*[BoardDao][deleteOneArticle]*/
    			FROM	BOARD
    			WHERE	BOARD_ID = #{boardId}
    	</delete>
    	
    </mapper>
    
    

    사용법 간단히 설명하자면
    namespace : 인터페이스명
    id : 사용할 메소드명
    parameterType : 매개변수 타입
    resultType : 리턴 타입(update, delete, insert 등의 int 리턴 타입은 태그 속성 생략한다)
    #{} : 매개변수 및 커맨드 객체 멤버 접근자. 매개변수나 커맨드 객체의 멤버에 대해 타입에 상관없이 접근 가능하도록 해준다. 사용자의 입장에서 데이터 타입을 고민할 필요가 없어진다. ( EL 표기법과 비슷 )
    (Dao 코드와 함께 부연설명)

    /*[BoardDao][getAllArticles]*/ : 로그로 쿼리문 검색 용이하도록 하는 주석. 실무 룰이라고 한다.

    ※ SELECT 쿼리문의 경우 쿼리에 맞는 결과가 있다면 이를 return 값인 커맨드 객체에 매핑 시켜야 한다. dao 코드에서 rs.getxxx() 메소드를 사용했지만 여기서는 객체 멤버변수명에 맞는 별칭을 주면 자동으로 매핑해준다.

    ※ parameterType 속성에서 _int가 보인다. 이는 typeAliasing으로 MyBatis에서 사용하는 별칭이다. _int는 자바에서 int에 해당한다. 이와 관련된 표는 다음과 같다.

    Mapper를 등록하면 이들을 등록하고, 관리할 수 있도록 해주는 xml 파일이 필요하다. configuration 정보를 등록할 수 있는 xml 파일을 생성한다.

    src/main/resources에서 마우스 오른쪽 - New - File 클릭

    mybatis.xml 파일명 작성 후 finish ( 필자는 만들어둬서 비활성화 )

    다음과 같이 생성해둔 mapper 태그를 등록해 관리한다. 이 또한 직접 입력해야 한다. 


    <?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">
    <!-- namespace : 인터페이스명, id : 사용할 메소드명 -->
    
    <?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>
    
    	<typeAliases>
    		<typeAlias type="com.blog.naver.board.vo.BoardVO" alias="BoardVO"/>
    	</typeAliases>
    	
    	<mappers>
    		<mapper resource="com/blog/naver/board/dao/sql/boardDaoSql.xml" />
    	</mappers>
    	
    </configuration>

    resources : mapper 파일의 패키지 포함 경로.
    typeAliases : 자바 타입(클래스)을 짧게 사용하기 위해 별칭을 준다. 오직 XML 설정에서만 사용된다.
    type : 클래스 경로
    alias : 별칭.

    이제 Dao 코드 작성하면 된다.

    SqlSessionTemplate 멤버로 갖고 있는 SqlSessionDaoSupport 클래스를 상속받아 getSqlSession()의 메소드들을 이용하면 된다. dao 코드가 한줄로 끝나게 되는 것이다! 코드는 다음과 같다.



    package com.blog.naver.board.dao;
    
    import java.util.List;
    
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import com.blog.naver.board.vo.BoardVO;
    
    public class BoardDaoImpl extends SqlSessionDaoSupport implements BoardDao{
    
    	
    
    	@Override
    	public List getAllArticles() {
    		// namespace, id 
    		return getSqlSession().selectList("BoardDao.getAllArticles");
    	}
    	
    	@Override
    	public int insertOneArticle(BoardVO boardVO) {
    		
    		return getSqlSession().insert("BoardDao.insertOneArticle", boardVO);
    	}
    	
    	@Override
    	public BoardVO selectOneArticle(int boardId) {
    		return getSqlSession().selectOne("BoardDao.selectOneArticle", boardId);
    	}
    	
    	@Override
    	public int deleteOneArticle(int boardId) {
    		return getSqlSession().delete("BoardDao.deleteOneArticle", boardId);
    	}
    }
    

    주 사용 메소드는
    selectList
    selectOne
    insert
    update
    delete
    의 5가지이고 매개변수가 있다면 , 와 함께 추가입력하면 된다.

    ※ insert나 delete 메소드에서 커맨드 객체나 primitive 타입을 매개변수로 주고 있다. #{} 표기법에서는 커맨드 객체의 경우 안에 멤버변수명을, primitive 타입의 경우 지정해둔 변수명을 이용해boardDaoSql.xml 파일에서 접근 가능하다.



Designed by Tistory.