열심히 끝까지

디바이스 융합 자바(Java) day79 - Mybatis 프레임워크를 Spring에 연동 본문

디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)

디바이스 융합 자바(Java) day79 - Mybatis 프레임워크를 Spring에 연동

노유림 2022. 10. 5. 16:01

[ Mybatis 프레임워크를 Spring에 연동 ]

 

지금까지 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
처럼 org.springframework에서 받아왔었음.

>> 그렇다면 Mybatis는??
    : Mybatis에서 Spring에게 연동에 필요한 API를 제공

 

연동하기 위한 방법

1) pom.xml에 dependency 추가

<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>1.2.4</version>
</dependency>

>> MyBatis를 Spring에 추가하고 나서의 모든 Mybatis 코드

<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>3.3.1</version>
</dependency>
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>1.2.4</version>
</dependency>
<!-- 
<dependency>
	<groupId>org.apache.ibatis</groupId>
	<artifactId>ibatis-core</artifactId>
	<version>3.0</version>
</dependency>
-->

>> 이 세개가 충돌이 일어나는 경우가 존재해 Spring에 연동할 때는 ibatis는 잠시 지우기

 

2) db.properties 파일 삭제 + 설정 제거(sql-map-config.xml에서 제거)

   (이미 DB 정보가 스프링 설정파일에 존재하기 때문에 중복 제거)

      : 나중에 사용할 수 있으니 기억해 둘 것(디바이스 융합 자바 day78에 db.properties 참고)

  - 스프링 설정 파일(applicationContext.xml) "dataSource"로 등록되어 있음

    >> 이름을 다르게 설정할 수도 있기 때문 이름 설정하는 것을 잘 기억할 것

 

3) SqlSessionFactory 클래스(우리 실습에서는 SqlSessionBean이름으로 존재)를 
   스프링 설정 파일(applicationContext.xml)에 <bean> 등록 해야 함

<bean class="org.mybatis.spring.SqlSessionTemplate">
	<constructor-arg ref="sqlSession" />
</bean>

   => SqlSessionFactory 객체로부터 DB연동에 사용할 SqlSession 객체를 얻기 위함
        (위의 설정과 같이 해주어야 함)

 

4) Mybatis를 이용한 DAO 클래스를 구현할 준비 완료!
    >> 멤버변수 Mybatis에게 SqlSessionTemplate 클래스 <bean> 등록하여 DI

 

 

위의 Mybatis를 Spring에 적용한 코드

 

applicationContext.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"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">

	<context:component-scan base-package="com.ryo.biz" />
	
	<aop:aspectj-autoproxy/>
	
	<!-- DataSource 설정하기 JDBCUtil 격 -->
	<!-- drivername, user, password, url을 입력받아야함 -->
	<!-- setter인젝션 사용(의존성 주입) -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"></property>
		<property name="username" value="ryo"></property>
		<property name="password" value="1234"></property>
	</bean>
	<!-- Spring에서 사용하는 JDBC 방법(테이블 제작) -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!-- Mybatis를 Spring에 연동 클래스가 org.mybatis로 시작-->
	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="configLocation" value="classpath:sql-map-config.xml" />
		<!-- 이미 존재하는 곳에서 가져오기 상황 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
	<bean class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg ref="sqlSession" />
	</bean>
</beans>

 

BoardDAO3.java(BoardServiceImpl에서 BoardDAO3로 변경)---------------

package com.ryo.biz.board.impl;

import java.util.List;

//import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.ryo.biz.board.BoardVO;
//import com.ryo.biz.common.SqlSessionBean;

@Repository("boardDAO")
public class BoardDAO3 {
	
	@Autowired
	private SqlSessionTemplate mybatis;
	
	public BoardVO selectOneBoard(BoardVO vo) {
		return mybatis.selectOne("BoardDAO.selectOneBoard",vo);
	}
    
	// 글 모두 보기
	public List<BoardVO> selectAllBoard(BoardVO vo) {
		return mybatis.selectList("BoardDAO.selectAllBoard",vo);
		/*
		 * if(vo.getSearchCondition()=="TITLE") { return
		 * mybatis.selectList("BoardDAO.selectAllBoardTitle",vo); }else { return
		 * mybatis.selectList("BoardDAO.selectAllBoardWriter",vo); }
		 */
	}
	
	
	// 글 추가
	public void insertBoard(BoardVO vo) {
		System.out.println("BoardDAO3 작동했어욤★");
		mybatis.insert("BoardDAO.insertBoard",vo);
	}
	// 글 업데이트
	public void updateBoard(BoardVO vo) {
		mybatis.update("BoardDAO.updateBoard",vo);
	}
	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		mybatis.delete("BoardDAO.deleteBoard",vo);
	}	

}

 

MemberDAO3.java(MemberServiceImpl에서 MemberDAO3로 변경)------

package com.ryo.biz.member.impl;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.ryo.biz.member.MemberVO;

@Repository("memberDAO")
public class MemberDAO3 {

	@Autowired
	private SqlSessionTemplate mybatis;

	// 로그인
	public MemberVO selectOneMember(MemberVO vo) {
		System.out.println("MemberDAO3 작동");
		return mybatis.selectOne("MemberDAO.selectOneMember", vo);
	}

	// 회원가입
	public void insertMember(MemberVO vo) {
		System.out.println("MemberDAO3 작동");
		mybatis.insert("MemberDAO.insertMember",vo);
	}
	
	// 글 업데이트
	public void updateMember(MemberVO vo) {
		mybatis.update("MemberDAO.updateMember",vo);
		// mybatis.commit();
	}
	
	// 글 삭제
	public void deleteMember(MemberVO vo) {
		mybatis.delete("MemberDAO.deleteMember",vo);
		// mybatis.commit();
	}	

}

 

sql-map-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>

   <!-- 별칭(Alias) 설정 -->
   <typeAliases>
      <typeAlias type="com.ryo.biz.board.BoardVO" alias="board"/>
      <typeAlias type="com.ryo.biz.member.MemberVO" alias="member"/>
   </typeAliases>
   
    <!-- SQL MAPPER 파일 연결 -->
   <mappers>
      <mapper resource="mappings/board-mapping.xml" />
      <mapper resource="mappings/member-mapping.xml" />
   </mappers>
   
</configuration>

 

mappings/board-mapping.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="BoardDAO">
<!-- sql 명령어를 한가득 담을텐데 그 때 부를 이름을 매핑 시키기 위해 namespace에 작성 -->
<!-- namespace는 필수속성이기에 매핑할 DAO 꼭 작성 -->

	<!-- 필요한 조 사용 -->
	<resultMap type="board" id="boardResult">
		<id property="bid" column="BID" />
		<result property="title" column="TITLE" />
		<result property="writer" column="WRITER" />
		<result property="content" column="CONTENT" />
	</resultMap>

	<!-- namespace 내부에 id는 중복 불가(하지만 다른 xml에 현재 있는 id가 있어도 괜찮음) -->
	<!-- 사진을 추가하지 않을 때, default 이미지 추가 | 추가하면 그 값 대입 -->
	<insert id="insertBoard">
		INSERT INTO BOARD(BID,TITLE,WRITER,CONTENT,UPLOADFILE) 
		VALUES((SELECT NVL(MAX(BID),0)+1 FROM BOARD),
		#{title},
		#{writer},
		#{content},
		<if test="fileName == null">
			default.jpg
		</if>
		<if test="fileName != null">
			#{fileName}
		</if>
		)
	</insert>
	
	<update id="updateBoard">
		UPDATE BOARD SET TITLE=#{title}, CONTENT=#{content}, UPLOADFILE=#{fileName} WHERE BID=#{bid}
	</update>
	
	<delete id="deleteBoard">
		<![CDATA[
		DELETE BOARD WHERE BID=#{bid}
		]]>
		<!-- DELETE BOARD WHERE BID<=20 처럼 부등호가 쓰고 싶다면?(태그로 인식되는 문자열) -->
	</delete>
	
	<!-- select는 output이 존재하기 때문에 누구랑 맞출 것인지 적어주어야 함 resultType="얼라이어스/별칭" -->
	<!-- 이름이 달라 서로 이어주지 못하기 때문에 직접 연결하여 값 가져오기 -->
	<select id="selectOneBoard" resultType="board">
		SELECT 
		 BID,
		 TITLE,
		 WRITER,
		 CONTENT,
		 CNT,
		 REGDATE,
		 UPLOADFILE AS fileName
		 
		 FROM BOARD WHERE BID=#{bid}
	</select>
	
	<!-- 다음과 같이 위에서 Map으로 묶어서 output 제공  -->
	<select id="selectAllBoard" resultMap="boardResult">
		SELECT * FROM BOARD 
		WHERE 1 = 1
		<if test="searchCondition == 'TITLE'">
			AND TITLE LIKE '%'||#{searchContent}||'%'
		</if>
		<if test="searchCondition == 'WRITER'">
			AND WRITER LIKE '%'||#{searchContent}||'%'
		</if>
		<if test="searchCondition == 'CONTENT'">
			AND CONTENT LIKE '%'||#{searchContent}||'%'
		</if>
		ORDER BY BID DESC
	</select>
    	<!-- 직접 나누어서 연결해주는 방법 -->
	<!-- 
	<select id="selectAllBoardTitle" resultMap="boardResult">
		SELECT * FROM BOARD 
		WHERE TITLE LIKE '%'||#{searchContent}||'%' 
		ORDER BY BID DESC
	</select>
	<select id="selectAllBoardWriter" resultMap="boardResult">
		SELECT * FROM BOARD 
		WHERE WRITER LIKE '%'||#{searchContent}||'%' 
		ORDER BY BID DESC
	</select>
 	-->
</mapper>

 

mappings/member-mapping.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="MemberDAO">

	<insert id="insertMember">
		INSERT INTO MEMBER(MID,MPW,NAME,ROLE) VALUES(#{mid},#{mpw},#{name},#{role})
	</insert>

	<update id="updateMember">
		UPDATE MEMBER SET MPW=#{mpw}, NAME=#{name} WHERE MID=#{mid}
	</update>
	
	<delete id="deleteMember">
		<![CDATA[
		DELETE MEMBER WHERE MID=#{mid}
		]]>
	</delete>
	
	<!-- select는 output이 존재하기 때문에 누구랑 맞출 것인지 적어주어야 함 resultType="얼라이어스/별칭" -->
	<select id="selectOneMember" resultType="member">
		SELECT * FROM MEMBER WHERE MID=#{mid} AND MPW=${mpw}
	</select>

</mapper>

 

 

 


 

 

+) 동적 SQL문 ( Dynamic SQL )
 > Mybatis는 SQL의 유연성을 향상시키려고 Dynamic SQL을 지원해 줌
    > 동적 엘리먼트(동적 요소, 동적 태그)를 사용해서 SQL문 처리 가능

<select id="selectAllBoard" resultMap="boardResult">
	SELECT * FROM BOARD 
	WHERE 1 = 1
	<if test="searchCondition == 'TITLE'">
		AND TITLE LIKE '%'||#{searchContent}||'%'
	</if>
	<if test="searchCondition == 'WRITER'">
		AND WRITER LIKE '%'||#{searchContent}||'%'
	</if>
	<if test="searchCondition == 'CONTENT'">
		AND CONTENT LIKE '%'||#{searchContent}||'%'
	</if>
	ORDER BY BID DESC
</select>

 

>> 1 = 1 : 연결을 원할하게 해주기 위한 것

 

BoardController에 scMap에 내용(Content)이라는 검색 추가
'내용'이라는 검색을 진행했을 때,