MyBatis 기반 CRUD 구현 및 핵심 속성 활용 가이드

1. MyBatis를 이용한 CRUD 기초 구현

MyBatis를 사용하여 데이터베이스의 기본적인 생성(Create), 조회(Read), 수정(Update), 삭제(Delete) 기능을 구현하는 방법은 인터페이스 정의, XML 매퍼 작성, 그리고 이를 실행하는 서비스 로직으로 구성됩니다.

MemberMapper 인터페이스 정의

public interface MemberMapper {
    void addMember(Member member);
    void modifyMember(Member member);
    void removeMember(String memberId);
    Member findMemberById(String memberId);
    List<Member> findAllMembers();
}

MemberRepositoryImpl 구현체

SqlSessionFactory를 주입받아 SqlSession을 통해 SQL을 실행하는 전형적인 구현 방식입니다.

public class MemberRepositoryImpl implements MemberMapper {
    private final SqlSessionFactory sessionFactory;

    public MemberRepositoryImpl(SqlSessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public void addMember(Member member) {
        try (SqlSession session = sessionFactory.openSession()) {
            session.insert("member.addMember", member);
            session.commit();
        }
    }

    @Override
    public void modifyMember(Member member) {
        try (SqlSession session = sessionFactory.openSession()) {
            session.update("member.modifyMember", member);
            session.commit();
        }
    }

    @Override
    public void removeMember(String memberId) {
        try (SqlSession session = sessionFactory.openSession()) {
            session.delete("member.removeMember", memberId);
            session.commit();
        }
    }

    @Override
    public Member findMemberById(String memberId) {
        try (SqlSession session = sessionFactory.openSession()) {
            return session.selectOne("member.findMemberById", memberId);
        }
    }

    @Override
    public List<Member> findAllMembers() {
        try (SqlSession session = sessionFactory.openSession()) {
            return session.selectList("member.findAllMembers");
        }
    }
}

MemberMapper.xml 구성

<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="member">
    <resultMap type="Member" id="MemberMap">
        <id column="mem_id" property="memberId" />
        <result column="mem_name" property="name" />
        <result column="mem_regdate" property="regDate" />
        <result column="mem_phone" property="phone" />
    </resultMap>

    <insert id="addMember" parameterType="Member">
        INSERT INTO members (mem_id, mem_name, mem_regdate, mem_phone)
        VALUES (#{memberId}, #{name}, #{regDate}, #{phone})
    </insert>

    <update id="modifyMember" parameterType="Member">
        UPDATE members SET mem_name=#{name}, mem_phone=#{phone} 
        WHERE mem_id=#{memberId}
    </update>

    <delete id="removeMember" parameterType="string">
        DELETE FROM members WHERE mem_id=#{memberId}
    </delete>

    <select id="findMemberById" resultMap="MemberMap" parameterType="string">
        SELECT * FROM members WHERE mem_id=#{memberId}
    </select>

    <select id="findAllMembers" resultMap="MemberMap">
        SELECT * FROM members
    </select>
</mapper>

2. MyBatis 결과 처리: resultMap과 resultType

조회 결과를 Java 객체에 매핑할 때 두 가지 주요 속성을 사용합니다.

  • resultMap: 복잡한 매핑이 필요하거나 DB 컬럼명과 객체 필드명이 다를 때 미리 정의한 매핑 설정을 참조합니다.
  • resultType: 컬럼명과 필드명이 일치할 때 클래스 경로를 직접 지정합니다. 기본 타입(Integer, String 등)이나 Map을 사용할 수도 있습니다.

다양한 리턴 타입 예시

<!-- 단일 값 조회 -->
<select id="getTotalCount" resultType="int">
    SELECT COUNT(*) FROM members
</select>

<!-- 별칭을 이용한 resultType 매핑 -->
<select id="findMemberWithAlias" resultType="cn.mybatis.domain.Member">
    SELECT mem_id AS memberId, mem_name AS name FROM members
</select>

<!-- Map 형태의 결과 반환 -->
<select id="findMemberAsMap" resultType="map">
    SELECT * FROM members
</select>

3. 파라미터 타입 처리 (parameterType)

SQL 문에 전달되는 매개변수의 타입을 지정합니다. 단일 값, 객체, 또는 Map을 전달할 수 있습니다.

<!-- Map을 이용한 다중 조건 검색 -->
<select id="searchByPeriod" parameterType="map" resultMap="MemberMap">
    <![CDATA[
    SELECT * FROM members
    WHERE mem_regdate BETWEEN #{start} AND #{end}
    ]]>
</select>

4. #{}와 ${} 문법의 차이점

MyBatis에서 변수를 바인딩하는 방식은 크게 두 가지로 나뉩니다.

#{} (Prepared Statement 방식)

  • 전달된 값을 SQL 쿼리의 파라미터로 처리하며 자동으로 따옴표(')를 추가하거나 타입을 변환합니다.
  • 보안성: SQL Injection 공격을 방어할 수 있어 가장 권장되는 방식입니다.

${} (Direct Substitution 방식)

  • 전달된 값을 쿼리 문자열에 그대로 치환합니다.
  • 용도: 테이블 이름이나 컬럼 이름처럼 쿼리의 구조 자체가 동적으로 변해야 할 때 사용합니다.
  • 위험성: SQL Injection에 취약하므로 사용자 입력값을 그대로 전달해서는 안 됩니다.

비교 예시

<!-- 안전한 방식: id가 'admin'인 경우 WHERE id = 'admin'으로 변환됨 -->
SELECT * FROM users WHERE id = #{userId}

<!-- 위험할 수 있는 방식: dynamicColumn이 'user_id'인 경우 SELECT user_id FROM... 으로 변환됨 -->
SELECT ${dynamicColumn} FROM users

태그: MyBatis java SQL CRUD ORM

7월 29일 20:08에 게시됨