공공부하자개발 · 영어 학습 노트
자바
실무 확장Excel · 파일 업로드 · DB 연동0/22 완료
  • 01Excel(XLSX) 구조와 순수 JDK로 읽기/쓰기
  • 02Apache POI로 Excel 업로드/다운로드
  • 03파일 업로드/다운로드 서버 (HttpServer)
  • 04JDBC 기초와 트랜잭션 (H2)
  • 05MyBatis 어노테이션 매퍼로 쿼리 연동
  • 06MyBatis XML 매퍼 · Oracle 방언 · PageHelper · Spring Boot
  • 07REST API 서버와 JSON
  • 08Vue 3 SPA 와 Java 서버 연동
  • 09@Scheduled 운영
  • 10로깅 실무: 레벨·계층, MDC 추적, 예외·성능, 마스킹, 롤링, JSON 로그
  • 11외부 API 연동
  • 12테스트 실무
  • 13암호화·개인정보 보호
  • 14인코딩·한글 실무
  • 15@Transactional 심화
  • 16긴 작업 비동기 처리와 진행률
  • 17SFTP·FTP 파일 연계
  • 18로컬 캐시와 @Cacheable
  • 19메일·알림 발송
  • 20웹 보안 체크리스트
  • 21빌드 도구와 폐쇄망 의존성 반입
  • 22성능 측정: p50·p95·p99, 측정 계층, JFR, JMH 함정, 자체 부하 테스트, 병목 순위
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 실무 확장 › 06 / 22

MyBatis XML 매퍼 · Oracle 방언 · PageHelper · Spring Boot

섹션 7진행 0 / 22
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

5. 자주 하는 실수 (Tip)

❌ 실수 1: JOIN resultMap 에 collection 을 넣고 autoMapping 을 잊는다

xml
<resultMap id="memberWithOrders" type="Member" extends="memberMap">                    <!-- ❌ name, joinedAt … 전부 null -->
<resultMap id="memberWithOrders" type="Member" extends="memberMap" autoMapping="true">  <!-- ✅ -->

기본 autoMappingBehavior=PARTIAL 은 중첩 매핑이 있는 resultMap 에 자동 매핑을 하지 않습니다. 증상이 "예외 없이 필드가 null" 이라 원인을 찾기 어렵습니다. 예제 6 에서 실제로 겪은 문제입니다.

❌ 실수 2: boolean 과 _boolean 별칭을 혼동한다

xml
<typeHandler handler="YesNoTypeHandler" javaType="boolean"/>    <!-- ❌ java.lang.Boolean 에만 등록. 원시형 boolean 필드는 기본 핸들러 → CHAR(1) 에 "TRUE" 저장 시도 → 오류 -->
<typeHandler handler="YesNoTypeHandler" javaType="_boolean"/>   <!-- ✅ 원시형. 래퍼는 boolean 또는 java.lang.Boolean -->

MyBatis 내장 별칭은 원시형에 _ 접두어를 붙입니다. _int, _long, _boolean 이 원시형이고 int, long, boolean 이 래퍼입니다. resultType 에도 같은 규칙입니다. resultType="long" 은 Long, resultType="_long" 은 long. 이 레슨을 작성하며 처음 실행에서 바로 이 오류가 났습니다.

❌ 실수 3: < 를 이스케이프하지 않는다

xml
<if test="to != null">AND joined_at <= #{to}</if>                  <!-- ❌ XML 파싱 오류: 요소 이름이 잘못됨 -->
<if test="to != null"><![CDATA[ AND joined_at <= #{to} ]]></if>    <!-- ✅ 또는 &lt;= -->

test 속성 안의 < 도 마찬가지입니다. test="a &lt; b" 로 씁니다. 반대로 CDATA 안에 <if> 를 넣으면 태그가 아니라 문자열로 취급되어 SQL 에 <if …> 가 그대로 들어가 SQL 오류가 납니다.

❌ 실수 4: Oracle 에서 null 을 바인딩하고 ORA-17004 를 본다

xml
INSERT INTO member (…, email) VALUES (…, #{email})                 <!-- ❌ email 이 null 이면 Invalid column type -->
INSERT INTO member (…, email) VALUES (…, #{email, jdbcType=VARCHAR})   <!-- ✅ 개별 지정 -->
<setting name="jdbcTypeForNull" value="NULL"/>                     <!-- ✅ 전역. 대부분 이걸로 끝 -->

Oracle JDBC 는 setNull(i, Types.OTHER) 를 거부합니다. MyBatis 기본 jdbcTypeForNull 이 OTHER 라 null 이 처음 들어오는 순간 터집니다. H2/MariaDB 에서 개발하고 Oracle 운영에 올렸을 때 첫날 만나는 오류입니다.

❌ 실수 5: 페이징 지시를 남긴다

java
Page.start(1, 20);
if (!valid(cond)) return List.of();      // ❌ 조회 없이 반환 → 지시가 남아 다음 조회에 페이징이 걸림
List<Member> list = mapper.search(cond);

try { Page.start(1, 20); return mapper.search(cond); } finally { Page.clear(); }   // ✅

PageHelper 도 같습니다. 예제 4 가 재현한 대로 캐시 히트, 예외, 조기 반환 어느 것이든 SQL 이 실행되지 않으면 지시가 살아남습니다. 증상이 "가끔 다른 화면 목록이 비어 있다"라 재현이 어렵습니다.

❌ 실수 6: resultType="map" 의 키를 소문자로 꺼낸다

java
Map<String, Object> row = mapper.monthlyJoinStats().get(0);
row.get("ym");                    // ❌ null. Oracle(그리고 H2 Oracle 모드)은 컬럼명을 대문자로 돌려준다 → 키는 "YM"
row.get("YM");                    // ✅ 하지만 MariaDB 에서는 "ym" 이라 벤더에 따라 깨진다

Map 결과는 DB 마다 키 대소문자가 다릅니다. 통계·리포트도 DTO(record) 로 받아 mapUnderscoreToCamelCase 에 맡기는 것이 벤더 중립적입니다. 꼭 Map 이어야 하면 AS "ym" 처럼 따옴표 별칭으로 대소문자를 고정합니다.

❌ 실수 7: XML id 오타를 배포 후에 발견한다

java
// 기동 시 한 번: 매퍼 인터페이스의 모든 메서드에 statement 가 있는지 확인
for (Class<?> mapper : conf.getMapperRegistry().getMappers())
    for (Method m : mapper.getMethods())
        if (!conf.hasStatement(mapper.getName() + "." + m.getName()))
            throw new IllegalStateException("XML 에 없는 statement: " + mapper.getName() + "." + m.getName());

컴파일러가 잡지 못하는 연결을 기동 시점 검사로 앞당깁니다. Spring 이면 @PostConstruct 나 ApplicationRunner 에, 아니면 테스트 하나에 둡니다. 10줄로 "잘못된 화면 눌렀을 때 500 에러"를 "기동 실패"로 바꿉니다.

자주 하는 실수 (Tip)
  • ❌ 실수 1: JOIN resultMap 에 collection 을 넣고 autoMapping 을 잊는다
  • ❌ 실수 2: boolean 과 _boolean 별칭을 혼동한다
  • ❌ 실수 3: < 를 이스케이프하지 않는다
  • ❌ 실수 4: Oracle 에서 null 을 바인딩하고 ORA-17004 를 본다
  • ❌ 실수 5: 페이징 지시를 남긴다
  • ❌ 실수 6: resultType="map" 의 키를 소문자로 꺼낸다
  • ❌ 실수 7: XML id 오타를 배포 후에 발견한다
이전 섹션4 응용 변형 예제5 / 7다음 섹션6 연습 문제