Spring, Mybatis

3-1. 0903_ MyBatis 더 알아보기

55yudi 2021. 9. 3. 14:14

- Mapping 개념

  xml을 이용한다.

- 가장 널리 사용되는 Java ORM Framework

- 소스코드에서 SQL Query 부분을 유연하게 관리할 수 있다는 특징

 

MyBatis의 개요


- 이클립스 장터에서 MyBatipse 플러그인을 선택하여 설치 (플러그인 이름 오타 아님,,)

- MyBatis 디펜던시 추가

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>

 

- MyBatis Spring 디펜던시 추가

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.6</version>
</dependency>

 

- mapper-emp.xml만들기

src폴더에서 마우스 우클릭 - new - other - mapper검색 - mybatis xml mapper 선택 후 이름 지정

 

- spring bean xml SqlSessionFactoryBean 정의 코드 context-spring-annotation.xml에 추가

<context-spring-annotation.xm 전체코드>

<?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:context="http://www.springframework.org/schema/context"
   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.3.xsd">
   
   <!-- DBCP 방식
   <bean id="dataSource"
      class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
      <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
      <property name="username" value="hr" />
      <property name="password" value="hr" />
   </bean>
     -->
    
   <!-- HikariCP 방식 -->
   <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <constructor-arg>
            <bean class="com.zaxxer.hikari.HikariConfig">
                <constructor-arg>
                    <props>
                        <prop key="jdbcUrl">jdbc:oracle:thin:@localhost:1521:xe</prop>
                        <prop key="username">hr</prop>
                        <prop key="password">hr</prop>
                    </props>
                </constructor-arg>
                <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
                <property name="minimumIdle" value="5" />
                <property name="maximumPoolSize" value="10" />
                <property name="connectionTestQuery" value="select 1 from sys.dual" />
                <property name="connectionTimeout"  value="300000" />
            </bean>
        </constructor-arg>
    </bean>
    	<!-- property name은 class마지막 부분 안에 있는 setter 함수 이름 -->
 	 	<!-- ref는 위쪽 bean id와 같아야 한다 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
     <property name="dataSource" ref="dataSource" />
     <property name="mapperLocations" value="classpath*:mapper-*.xml" />
   </bean>
   <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
     <constructor-arg index="0" ref="sqlSessionFactory" />
   </bean>
   
   <context:annotation-config></context:annotation-config>
   <context:component-scan
      base-package="myspringmybatis"></context:component-scan>
</beans>

* property name은 class마지막 부분 안에 있는 setter 함수 이름

* ref는 bean id와 같아야 한다.

* constructor-arg 는 생성자 매개변수

 


c.f. 클래스 vs 테이블

     - 코딩은 클래스로

     - DB는 테이블로 저장

     - ORM (OR Mapping)

 

Mapping 파일

- SQL이나 OR 매핑을 XML파일로 기술한 파일

             (=ORM, Object–Relational Mapping tool for the Java programming language)

- 하나의 애플리케이션에는 복수 개의 매핑 파일이 만들어 진다.

- NameSpace
   * 매핑 파일의 Root Element(최상위)의 속성으로 지정한다.
   * 매핑 파일에 기술된 SQL문장들을 그룹으로 묶는 역할을 한다.

 

* dtd (data type definition)를 보면 상위태그에 맞춰 어떤 하위 태그를 써야 하는지 보여줌

ctrl + 스페이스바를 해도 하위태그로 뭘 써야하는지 보여줌

- SQL 문장의 기술
<mapper-emp.xml>  

  * select, update, insert, delete라는 이름의 태그를 사용한다.
    <select id=“sql문장의ID(메소드 이름)” parameterType=“매개변수” resultType=“리턴타입”>

<!-- select 부서번호를 전달받아서 그 부서에 근무하는 사원목록을 리턴함
		메소드 : List<EmpVO> getEmpListByDeptId(int deptId) -->
<select id="getEmpListByDeptId" parameterType="int" resultType="myspringmybatis.EmpVO"></select>


    * id : SQL 문장의 식별자 역할을 수행한다.
    * parameterTpye : 전달될 매개변수를 지정한다.
    * resultType : 리턴타입을 지정한다.

sql문을 사이에 쓸 수 있다.

<mapper-emp.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="mapper-emp">
<!--  select부서번호를 전달받아서 그부서에 근무하는 사원목록을 리턴함
			List<EmpVO> getEmpListByDeptId(int deptId) 이 부분에서
           getEmpListByDeptId , List<EmpVO>, int deptId
       <select id=“sql문장의ID(메소드 이름)” parameterType=“매개변수” resultType=“리턴타입”>-->  
       <select id="getEmpListByDeptId" parameterType="int" resultType="myspringmybatis.EmpVO">
             select employee_id employeeId,
                   last_name lastName
             from employees
             where department_id = #{deptId}
             
       </select>

</mapper>

 

- <bean id="sqlSessionFactory" 이 부분을 EmpDAO.java에 쓰는 방법

package myspringmybatis;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

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

@Component
public class EmpDAO {
	
//	@Autowired
//	DataSource dataSource;
	
	@Autowired
	SqlSessionTemplate sqlSession;

   public List<EmpVO> getEmpListByDeptId(int deptId) throws Exception  {
	   return sqlSession.selectList("getEmpListByDeptId", deptId);
      
//	  ArrayList<EmpVO> result = new ArrayList<EmpVO>();
//	  
////      Class.forName("oracle.jdbc.driver.OracleDriver");
////      Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","hr","hr");
//	  
//	  Connection con = dataSource.getConnection();
//      String sql = "select * from employees where department_id = ?";
//      PreparedStatement stmt = con.prepareStatement(sql);
//      stmt.setInt(1, deptId);
//      ResultSet rs = stmt.executeQuery();
//      while(rs.next()) {
//         //EmpVO객체를 만들고 객체변수에 데이터베이스의 데이터로 설정하고
//         EmpVO vo = new EmpVO();
//         vo.employeeId = rs.getInt("employee_id");
//         vo.lastName = rs.getString("last_name");
//         result.add(vo);
//         
//      }
//      return result;
   }
}

↑ 기존에 오라클 커넥션을 위한 긴 코드가 전부 불필요하게 되고

    단 몇 줄 만으로 간단하게 wiring이 됨

 

<EmpDAO.java 전체코드(다시 수정함)>

package myspringmybatis;

import java.util.List;

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

@Component
public class EmpDAO {

	@Autowired
	SqlSession sqlSession;

   public List<EmpVO> getEmpListByDeptId(int deptId) throws Exception  {
	   return sqlSession.selectList("getEmpListByDeptId",deptId);

   }
}

 

아직은 오류가 남

NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy

- sql 코드 수정

<select id="getEmpListByDeptId" parameterType="int" resultType="myspringmybatis.EmpVO">
             select employee_id employeeId,
                   last_name lastName
             from employees
             where department_id = #{deptId}
             
       </select>

 

- spring-jdbc 디펜던시 추가

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.0.20.RELEASE</version>
</dependency>

 

- 실행하면 나오는 콘솔 결과

 

- 한번에 import하는 방법 : ctrl + shift + O

 

- Alias(별칭)

- 노랑부분 : EmpVO 안에 있는 변수 이름이기 때문에 일치시켜줘야 한다.

 

- 실습하기(과제)

현재의 프로젝트에 추가합니다.
- 사용자로부터 사번을 입력받아서 그 사원의 (사번, 이름, 부서번호, 급여, 이메일)을 출력합니다.
- 0번을 입력하면 종료, 반복합니다.

1. EmpVO에 변수추가
2. EmpDAO에 메서드 추가
3. 매퍼 수정
4. EmpMain이라는 메인메서드가 있는 클래스 생성
테스트합니다.