[JPA] MyBatis로 DB 연동하기

박이레·2022년 9월 15일
0

JPA

목록 보기
3/6
post-thumbnail

 myBatis는 SQL 매퍼 프레임워크입니다. '매퍼 프레임워크'.. 단어가 어렵지요?

단어는 차치하고 myBatis는 왜 개발됐을까요? myBatis는 JDBC 단점 때문에 등장했습니다. JDBC의 단점은 뭘까요?

① 중복 코드 작성(getConnection, close)
② SQL 구문이 DAO에 포함
JDBC 장·단점이 궁금하시다면..🧷

myBatis는 이 두가지 문제를 해결했습니다.

① 더이상 중복 코드를 작성하지 않아도 되죠. Connection, close를 myBatis가 대신 처리합니다.

② SQL이 변경되더라도 자바 소스를 변경하지 않아도 됩니다. SQL 구문은 xml 파일을 만들어서 관리합니다.

DB연동이 얼마나 편해졌는지 한번 살펴볼까요?


실습 순서는 다음과 같습니다.

① VO(Value Object) 작성
② SQL Mapper 작성
③ myBatis 메인 설정 파일 작성
④ DAO(Data Access Object) 작성
⑤ Client 작성


1. VO

VO는 JDBC 실습에서 사용한 것과 동일합니다.

package com.rubypaper.persistence.mybatis;

import lombok.Data;

import java.sql.Timestamp;

@Data
public class EmployeeVO {

    private Long id;
    private String name;
    private Timestamp startDate;
    private String title;
    private String deptName;
    private Double salary;
}

2. SQL mapper

SQL Mapper XML 등록된 SQL은 중복되지 않는 id를 가져야 합니다. (아래에서는 insertEmployee, getEmployeeList라고 작성했습니다.

insertEmployee는 parameterType으로 employeeVO 객체를 받아서 바인딩하고 있습니다. (코드에서 employee는 EmployeeVO의 별칭(Alias)입니다. myBatis 메인 설정파일에서 별칭을 선언할 수 있습니다.)

getEmployeeList는 파라미터가 없어서 parameterType 속성을 사용하지 않았습니다. 검색 결과가 EmployeeVO 객체에 매핑되도록 resultMap 속성을 사용했습니다.

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper PUBLIC "-//matabis.org//DTD Mapper 3.0//EN" "http://mabatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="EmployeeDAO">

    <!--ResultMap 선언-->
    <resultMap type="" id="employeeResult">
        <result property="id" column="ID"/>
        <result property="name" column="NAME"/>
        <result property="startDate" column="START_DATE"/>
        <result property="title" column="TITLE"/>
        <result property="deptName" column="DEPT_NAME"/>
        <result property="salary" column="SALARY"/>
    </resultMap>

    <!--직원 등록 SQL-->
    <insert id="insertEmployee" parameterType="employee">
        INSERT INTO s_emp(id, name, start_date, title, dept_name, salary)
        VALUES((SELECT nvl(max(id), 0) + 1 FROM s_emp),
        #{name},
        #{startDate},
        #{title},
        #{deptName},
        #{salary},
    </insert>

    <!--직원 목록 검색 SQL-->
    <select id="getEmployeeList" resultMap="employeeResult">
        SELECT id, name, start_date, title, dept_name, salary
        FROM s_emp
        ORDER BY name
    </select>
</mapper>

3. myBatis 메인 설정 파일

① 별칭(Alias)를 설정합니다. 별칭은 SQL Mapper XML(s_emp_mapping.xml)에서 사용합니다.

② 데이터 소스를 설정합니다. 여기서는 H2 DB를 설정했습니다.

③ SQL Mapper XML(s_emp-mapping.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>

    <!--매퍼 XML(s_emp_mapping.xml)에서 사용할 Alias 선언-->
    <typeAliases>
        <typeAlias alias="employee" type="com.rubypaper.persistence.mybatis.EmployeeVO"/>
    </typeAliases>

    <!--데이터소스 설정-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="org.h2.Driver"/>
                <property name="url" value="jdbc:h2:tcp://localhost/~/test"/>
                <property name="username" value="sa"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>

    <!--매퍼 XML(s_emp_mapping.xml) 등록-->
    <mappers>
        <mapper resource="com/rubypaper/persistence/mybatis/s_emp_mapping"/>
    </mappers>
</configuration>

4. DAO

myBatis를 사용하려면 SqlSession 객체가 필요합니다. SqlSession 객체는 아래 방법으로 얻을 수 있습니다. (SqlSession에는 데이터 소스와 sql-map-config.xml에 설정한 정보가 들어 있습니다.)

① sql-map-config.xml을 로딩해서 SqlSessionFactory를 생성합니다.
② SqlSessionFactory의 openSession()을 통해 SqlSession을 생성합니다.

package com.rubypaper.persistence.mybatis;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

public class EmployeeDAO {

    private SqlSession mybatis;

    public EmployeeDAO() {

        try {
            Reader reader = Resources.getResourceAsReader("com/rubypaper/persistence/mybatis/sql-map-config.xml");
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
            mybatis = sessionFactory.openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void insertEmployee(EmployeeVO vo) {
        System.out.println("===> MyBatis 기반으로 회원 등록");
        mybatis.insert("EmployeeDAO.insertEmployee", vo);
        mybatis.commit();
    }

    public List<EmployeeVO> getEmployeeList() {
        System.out.println("===> MyBatis 기반으로 회원 목록 조회");
        return mybatis.selectList("EmployeeDAO.getEmployeeList");
    }
}

5. Client

Client는 DAO에 구현된 메서드의 기능을 확인합니다.

package com.rubypaper.persistence.mybatis;

import java.sql.Timestamp;
import java.util.List;

public class EmployeeServiceClient {

    public static void main(String[] args) {
        EmployeeVO vo = new EmployeeVO();
        vo.setName("둘리");
        vo.setStartDate(new Timestamp(System.currentTimeMillis()));
        vo.setTitle("사원");
        vo.setDeptName("영업부");
        vo.setSalary(1700.00);

        EmployeeDAO employeeDAO = new EmployeeDAO();
        employeeDAO.insertEmployee(vo);

        List<EmployeeVO> employeeList = employeeDAO.getEmployeeList();
        for (EmployeeVO employee : employeeList) {
            System.out.println("---> " + employee.toString());
        }
    }
}

실행 결과

JDBC에 비해 코드가 한결 간결해졌습니다. 그러나 여전히 SQL을 직접 관리해야 하는 번거로움이 있습니다.

myBatis의 단점을 보완하기 위해 ORM(Object-Relational Mapping) Framework가 등장했습니다. 다음 글에서는 ORM Framework 중 Hibernate로 DB 연동을 해보겠습니다.


완성 코드

💁‍♂️reference

JPA 퀵스타트

채규태 지음ㅣ루비페이퍼ㅣ2020ㅣ도서 정보

EOD.

profile
혜화동 사는 Architect

0개의 댓글