Java_35_MyBatis XML

OngTK·2025년 10월 13일

Java

목록 보기
35/35

0) application.properties 설정

mybatis.mapper-location=classpath:/폴더명/파일명.xml
mybatis.mapper-location=classpath:/*.xml

1) XML 매퍼 파일 골격

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="example.day13_251013.XmlMapper">
    <!-- SQL 구문들(insert/select/update/delete)이 이 안에 위치 -->
</mapper>
  • namespace매퍼 인터페이스의 FQCN(풀 패키지명 포함)과 동일하게 작성
  • DTD 선언은 MyBatis 3 매퍼 규격을 지정

2) 기본 CRUD 작성법

(A) INSERT — useGeneratedKeys 로 PK 자동 매핑

<insert id="save" parameterType="example.day13_251013.StudentDto"
        useGeneratedKeys="true" keyProperty="sno">
    INSERT INTO student(name, kor, math) values (#{name}, #{kor}, #{math});
</insert>
  • parameterType : 파라미터 DTO(또는 Map/기본형) 지정
  • useGeneratedKeys : DB가 생성한 PK를 DTO 필드(keyProperty)에 바인딩

(B) SELECT — 전체 조회

<select id="findAll" resultType="example.day13_251013.StudentDto">
  SELECT * FROM student;
</select>
  • resultType : 단일 레코드 타입(리스트로 받을 때도 요소 타입 지정)

(C) SELECT — 단건 조회(파라미터 1개)

<select id="find" parameterType="int" resultType="example.day13_251013.StudentDto">
  SELECT * FROM student WHERE sno = #{sno};
</select>
  • 기본형 파라미터 사용 시 바인딩 이름은 #{value} 또는 메서드 파라미터명이 sno 인 경우 #{sno} 사용 가능(Mapper 인터페이스에서 @Param 사용하면 명시적 이름 부여 가능)

(D) DELETE — 단건 삭제

<delete id="delete" parameterType="int">
  DELETE FROM student WHERE sno = #{sno};
</delete>

(E) UPDATE — DTO 기반 수정

<update id="update" parameterType="example.day13_251013.StudentDto">
  UPDATE student SET kor = #{kor}, math = #{math} WHERE sno = #{sno};
</update>

3) 동적 SQL(Dynamic SQL)

(A) if — 조건부 WHERE

<select id="query2" parameterType="int" resultType="example.day13_251013.StudentDto">
  SELECT * FROM student WHERE 1=1
  <if test="kor != null">
    AND kor >= #{kor}
  </if>
</select>
  • test 에는 OGNL 사용(kor != null, name != null && name != '' 등)

(B) where + if — 자동으로 선행 AND 정리

<select id="query3" resultType="example.day13_251013.StudentDto">
  SELECT * FROM student
  <where>
    <if test="name != null">
      AND name LIKE CONCAT('%', #{name}, '%')
    </if>
    <if test="math != 0">
      AND math >= #{math}
    </if>
  </where>
</select>
  • <where> 는 내부 첫 AND/OR를 자동으로 제거하여 문법 오류 방지

(C) foreach — 다건 INSERT / IN 절

<insert id="saveAll" parameterType="list" useGeneratedKeys="true" keyProperty="sno">
  INSERT INTO student(name, kor, math) VALUES
  <foreach collection="list" item="student" separator=",">
    (#{student.name}, #{student.kor}, #{student.math})
  </foreach>
</insert>
  • collection : list/array/map 등 컬렉션 이름
  • item : 각 요소를 지칭하는 변수명
  • separator : 요소 구분자(여기서는 콤마)

: IN 절에 사용 시 open="(" close=")" separator="," 를 지정

<select id="findIn" parameterType="list" resultType="example.day13_251013.StudentDto">
  SELECT * FROM student
  WHERE sno IN
  <foreach collection="list" item="id" open="(" separator="," close=")">
    #{id}
  </foreach>
</select>

4) 매퍼 인터페이스와의 연결

(A) 매퍼 인터페이스

@Mapper
public interface XmlMapper {
  int save(StudentDto dto);
  List<StudentDto> findAll();
  StudentDto find(@Param("sno") int sno);
  int delete(@Param("sno") int sno);
  int update(StudentDto dto);
  List<StudentDto> query2(@Param("kor") Integer kor);
  List<StudentDto> query3(@Param("name") String name, @Param("math") Integer math);
  int saveAll(@Param("list") List<StudentDto> list);
}
  • 메서드명 = XML의 id 로 매핑
  • 파라미터가 2개 이상이면 @Param 으로 바인딩 이름 지정 권장
  • 반환형과 resultType/resultMap 일치하도록 작성

(B) 컨트롤러 사용 예시

@RestController
@RequiredArgsConstructor
@RequestMapping("/xml")
public class XmlController {
  private final XmlMapper xmlMapper;

  @PostMapping
  public int save(@RequestBody StudentDto dto) { return xmlMapper.save(dto); }

  @GetMapping
  public List<StudentDto> findAll() { return xmlMapper.findAll(); }

  @GetMapping("/{sno}")
  public StudentDto find(@PathVariable int sno) { return xmlMapper.find(sno); }
}

5) DTO 예시

@Data
@AllArgsConstructor @NoArgsConstructor
public class StudentDto {
  private Integer sno;
  private String name;
  private Integer kor;
  private Integer math;
}

6) 베스트 프랙티스 & 체크리스트 ✅

  • namespace = 인터페이스 FQCN 일치 확인
  • parameterType/resultType 정확히 지정(패키지 포함)
  • 자동 PK 필요 시 useGeneratedKeys="true", keyProperty 설정
  • 동적 WHERE 는 <where> 로 안전하게 구성(선행 AND 제거)
  • 다건 파라미터는 @Param 또는 DTO/Map 으로 래핑
  • foreachcollection/item/separator 정확히 지정
  • 긴 SELECT 컬럼은 resultMap 으로 명시 매핑 고려(별칭 ↔ 필드명 매칭)
  • SQL 예약어/대소문자, 세미콜론(;) 사용 규칙 프로젝트 컨벤션 준수

7) 문제 해결 가이드(흔한 오류)

  • Parameter 'xxx' not found : @Param("xxx") 누락 또는 parameterType 불일치
  • Invalid bound statement : namespace 또는 id 불일치(인터페이스-XML 매핑 확인)
  • 자동 키 미반영 : DB 드라이버/테이블 PK 설정 확인 + useGeneratedKeys/keyProperty 재점검
  • 동적 SQL 문법 오류 : <where>, <if> 의 공백/개행, 괄호 짝 확인

8) 확장: resultMap 스니펫

컬럼명과 필드명이 다를 때 매핑 제어

<resultMap id="StudentMap" type="example.day13_251013.StudentDto">
  <id property="sno" column="sno"/>
  <result property="name" column="name"/>
  <result property="kor" column="kor"/>
  <result property="math" column="math"/>
</resultMap>

<select id="findAll2" resultMap="StudentMap">
  SELECT sno, name, kor, math FROM student
</select>

마무리

  • XML 매퍼는 SQL 가독성/재사용성이 높고, 동적 SQL로 다양한 검색/등록 시나리오를 유연하게 처리 가능
  • 위 예시를 템플릿 삼아 프로젝트 네이밍/패키지에 맞게 경로만 변경해 사용 권장
profile
2025.05.~K디지털_풀스택 수업 수강중

0개의 댓글