반응형
해당 글에서는 MyBatis에서 공통으로 사용하는 파라미터와 select, insert, update, delete 태그에서 사용되는 속성을 이해하고 예시를 확인해 봅니다.
1) MyBatis 공통 파라미터 종류
1. #{parameter}
💡 #{parameter}
- MyBatis에서 SQL 문에 파라미터를 바인딩하는 방법을 의미합니다. 이 방법은 PreparedStatement를 사용하여 SQL쿼리 내에서 안전하게 파라미터를 입력할 수 있습니다.
- 또한 이는 입력값을 문자열로 변환하지 않고, SQL이 실행되기 전에 안전하게 값을 대입하여 SQL Injection 공격에 안전합니다.
<!--사용자 리스트를 조회합니다.-->
<select id="selectUserList" parameterType="UserDto" resultType="UserDto">
SELECT t1.*
FROM TB_USER t1
WHERE t1.delYn = 0
AND t1.user_name = #{userName}
</select>
[ 더 알아보기 ]
💡 PreparedStatement
- SQL을 실행하기 전에 미리 컴파일하여 실행계획을 준비해 놓는 방식입니다. 이를 통해 동일한 SQL을 반복적으로 실행할 때, 성능을 향상할 수 있습니다.
- 또한, SQL Injection 공격을 방지하기 위해 사용됩니다. 사용자 입력을 이용해 쿼리를 작성할 때, #{}를 이용해 PreparedStatement를 생성하면, 입력값이 SQL 구문에 영향을 미치지 않고 안전하게 쿼리를 실행할 수 있습니다.
2. ${variable}
💡 ${variable}
- MyBatis에서 SQL문애 단순 문자열 치환의 목적으로 사용이 됩니다. 즉 변수의 값을 직접 SQL문에 넣는 형태로 사용합니다.
-해당 경우는 SQL Injection 공격에 위험이 있으므로 사용 시 주의가 필요합니다.
<!--변수로 받은 테이블 명을 통해 전체 데이터를 조회합니다. -->
<select id="getTable" parameterType="java.util.Map" resultType="java.util.Map">
SELECT *
FROM ${tableName}
ORDER BY ${orderName}
</select>
💡 [ 더 알아보기 ]
💡 #{variable}은 왜 SQL Injection에 위험한가?
- #{parameter}와 같이 PreparedStatement를 이용하여 미리 컴파일 단계에 실행 계획을 준비해 둔 상태가 아니고 #{variable}을 이용하면 공격자가 임의의 SQL문을 바로 입력하여 실행할 수 있기에 문제를 일으킬 수 있습니다.
2) MyBatis 파라미터 속성
💡 MyBatis 파라미터 속성
- 해당 속성은 ${parameter}를 하는 경우 함께 이용할 수 있는 파라미터의 속성에 대해 알아봅니다.
1. 속성 종류
parameter 속성 | 설명 |
jdbcType | JDBC에서 사용할 SQL 타입을 지정합니다. |
javaType | Java에서 사용할 타입을 지정합니다. (기본자료형, 래퍼클래스, 패키지 명, 커스텀 패키지 명을 사용이 가능합니다) |
mode | 프로시저를 위한 IN, OUT, INOUT 파라미터를 지정합니다. |
property | SQL 문에서 참조할 때 사용할 속성 이름을 지정합니다. |
jdbcTypeName | JDBC 타입의 이름을 지정합니다. |
typeHandler | 특정 타입의 핸들러를 지정합니다. |
numericScale | BigDecimal 객체를 사용할 때 필요한 스케일을 지정합니다. |
resultMap | JOIN이나 복잡한 SQL 쿼리 결과를 매핑하기 위해 사용되는 resultMap의 id를 지정합니다. |
💡 javaType, jdbcType 속성을 사용한 예시
- 파라미터로 들어오는 자바의 타입과 데이터베이스에 지정한 타입을 지정하여 해당 속성을 지정하였습니다.
<!-- 회원 정보를 조회합니다. -->
<select id="selectUser" resultType="User">
SELECT id, name, email, phone
FROM user
WHERE id = #{userId, javaType=int, jdbcType=INTEGER}
</select>
<!-- 회원의 이름을 업데이트 합니다. -->
<update id="updateUserName" parameterType="User">
UPDATE user
SET name = #{name, javaType=String, jdbcType=VARCHAR}
WHERE id = #{id, javaType=int, jdbcType=INTEGER}
</update>
💡 mode 속성을 사용한 예시
- 파라미터로 들어오는 값은 mode의 IN 값을 주고, 프로시저를 수행한 이후에 반환되는 값은 mode 값을 out으로 사용하였습니다.
<!--Dummy User를 등록하고 사용자 아이디에 따라 결과값을 반환받습니다. -->
<select id="procInsertFindUser" statementType="CALLABLE" parameterType="DummyUserDto">
CALL multiflex_scma.PROC_INSERT_FIND_USER(
#{piUserName, mode=IN, jdbcType=VARCHAR},
#{piFindUserId, mode=IN, jdbcType=VARCHAR},
#{poFindIdCnt, mode=OUT, jdbcType=INTEGER})
</select>
2. 속성 종류 상세 : jdbcType
💡 속성 종류 상세 : jdbcType
- MyBatis 내에서 사용되는 jdbcType으로 SQL 타입들을 명시합니다.
BIT | FLOAT | CHAR | TIMESTAMP | OTHER | UNDEFINED |
TINYINT | REAL | VARCHAR | BINARY | BLOB | NVARCHAR |
SMALLINT | DOUBLE | LONGVARCHAR | VARBINARY | CLOB | NCHAR |
INTEGER | NUMERIC | DATE | LONGVARBINARY | BOOLEAN | NCLOB |
BIGINT | DECIMAL | TIME | NULL | CURSOR | ARRAY |
3. 종류 상세 : javaType
💡 javaType
- javaType의 경우는 기본자료형, 래퍼클래스, 패키지, 커스텀 자바 타입이 사용이 가능합니다. 커스텀 자바 타입의 경우는 com.example.MyCustomType (클래스 경로 포함) 형태로 표현이 가능합니다.
JDBC Type | 기본 자료형 | 래퍼 클래스 | 패키지 명 |
BOOLEAN | boolean | Boolean | java.lang.Boolean |
BIT | x | Boolean | java.lang.Boolean |
SMALLINT | short | Short | java.lang.Short |
INTEGER | int | Integer | java.lang.Integer |
TINYINT | x | Byte | java.lang.Byte |
SMALLINT | x | Short | java.lang.Short |
BINARY | x | Byte[] | java.lang.Byte |
VARBINARY | x | Byte[] | java.lang.Byte |
LONGVARBINARY | x | Byte[] | java.lang.Byte |
BIGINT | x | Long | java.lang.Long |
BIGINT | long | Long | java.lang.Long |
REAL | x | Float | java.lang.Float |
DOUBLE | double | Double | java.lang.Double |
FLOAT | x | Double | java.lang.Double |
CHAR | char | Character | java.lang.Character |
VARCHAR | x | String | java.lang.String |
NVARCHAR | x | String | java.lang.String |
NCHAR | x | String | java.lang.String |
LONGVARCHAR | x | String | java.lang.String |
OTHER | x | Object | java.lang.object |
DATE | x | Date | java.sql.Date |
TIME | x | TIME | java.sql.time |
TIMESTAMP | x | TIMESTAMP | java.sql.timestamp |
BLOB | x | Blob | java.sql.Blob |
CLOB | x | Clob | java.sql.Clob |
CURSOR | x | ResultSet | java.sql.ResultSet |
ARRAY | x | List | java.util.List |
MAP | x | Map | java.util.Map |
SET | x | Set | java.util.Set |
NUMERIC | x | BigDecimal | java.math.BigDecimal |
DECIMAL | x | BigDecimal | java.math.BigDecimal |
3) select 태그 속성
1. select 태그 속성 종류
속성명 | 필수 여부 | 설명 |
id | 필수 | 고유 식별자 |
resultType | 필수 | 결과의 유형을 지정 |
parameterType | 선택 | 파라미터의 유형을 지정 |
parameterMap | 선택 | 파라미터를 맵핑하는 데 사용 |
resultMap | 선택 | 결과를 맵핑하는 데 사용 |
flushCache | 선택 | 캐시를 비우는지 여부를 지정 |
useCache | 선택 | 캐시를 사용하는지 여부를 지정 |
timeout | 선택 | 타임아웃 시간을 지정 |
fetchSize | 선택 | 한 번에 가져올 행의 수를 지정 |
statementType | 선택 | SQL 문의 유형을 지정(STATEMENT, PREPARED, CALLABLE) |
resultSetType | 선택 | 결과 세트의 유형을 지정(FORWARD_ONLY, SCROLL_SENSITIVE, SCROLL_INSENSITIVE) |
databaseId | 선택 | 데이터베이스 ID를 지정 |
resultOrdered | 선택 | 결과가 순서대로 정렬되는지 여부를 지정 |
resultSets | 선택 | 결과 세트를 지정 |
affectData | 선택 | 데이터에 미치는 영향을 지정 |
[ 더 알아보기 ]
💡 select 태그에서 parameterType 속성을 안 적는 경우가 많은데 왜 그럴까?
- select에서 parameterType은 필수가 아닌 선택적 속성입니다. 이는 MyBatis가 파라미터를 자동으로 매핑하고, 자바의 오버로딩 규칙을 따라서 파라미터 타입을 결정하기 때문입니다.
- SQL 쿼리에서 파라미터를 사용하지 않거나, MyBatis가 자동으로 파라미터 타입을 추론할 수 있는 경우 parameterType을 명시적으로 지정할 필요가 없습니다.
2. select 태그의 속성 사용 예시 -1: parameterType, resultType
💡 select 태그의 속성 사용 예시 -1: parameterType, resultType
- 일반적으로 가장 많이 사용하는 select 태그의 속성들에 대해 확인해 봅니다.
- parameterType : 파라미터로 전달될 데이터 타입 유형이며 해당 속성은 선택 사항이며 해당 속성을 사용하지 않더라도 자동으로 매핑됩니다.
- resultType : 결과값을 반환될 타입 유형
<select id="selectCodeList" parameterType="codeDto" resultType="codeDto" >
SELECT t1.*
FROM multiflex_scma.tb_code t1
WHERE t1.use_yn = true
<if test="grpCd != null">
AND t1.grp_cd = #{grpCd}
</if>
</select>
💡 [ 더 알아보기 ]
💡 해당 코드에서 codeDto라고만 적었는데 어떻게 매핑이 될까?
- MyBatis의 설정을 구성하는 DBConfig 파일 내에서 setTypeAliasesPackage로 매핑하였기에 기본적으로 model 패키지 아래 구성한 DTO를 보고 있습니다.
3. select 태그의 속성 사용예시 -2 : statementType
💡 select 태그의 속성 사용예시 -2 : statementType
- 조회에 프로시저로 사용되는 타입으로 statementType 속성을 ‘CALLABLE’로 구성합니다.
- statementType : STATEMENT, PREPARED, CALLABLE 중 하나를 선택.
<!--Dummy User를 등록하고 사용자 아이디에 따라 결과값을 반환받습니다. -->
<select id="procInsertFindUser" statementType="CALLABLE" parameterType="DummyUserDto">
CALL multiflex_scma.PROC_INSERT_FIND_USER(
#{piUserName, mode=IN, jdbcType=VARCHAR},
#{piFindUserId, mode=IN, jdbcType=VARCHAR},
#{poFindIdCnt, mode=OUT, jdbcType=INTEGER})
</select>
💡 [ 더 알아보기 ]
💡select 태그에서 프로시저를 구성했는데 insert, update, delete 관련 성격의 프로시저도 있는데, 꼭 select 태그만 써야 할까?
- MyBatis에서는 select, insert, update, delete에 해당하는 SQL을 실행하는데 각각의 태그를 제공하고 있습니다. 프로시저의 성격에 따라 적절한 태그를 사용하는 것이 좋습니다.
4) insert, update, delete 태그 속성
1. insert, update, delete 태그 속성 종류
💡 insert, update, delete 태그 속성은 모두 동일한 속성을 가집니다.
속성 명 | 필수 여부 | 설명 |
id | 필수 | 구문의 고유 ID |
parameterType | 필수 | 파라미터의 자바 타입 |
flushCache | 선택 | 구문 실행 후 캐시를 비울지 여부 |
timeout | 선택 | 구문 실행의 제한 시간 |
statementType | 선택 | 사용할 구문의 종류 (PREPARED, CALLABLE 등) |
useGeneratedKeys | 선택 | 자동 생성된 키를 사용할지 여부 |
keyProperty | 선택 | 자동 생성된 키를 설정할 속성 |
keyColumn | 선택 | 자동 생성된 키의 컬럼 |
databaseId | 선택 | 구문을 실행할 데이터베이스의 ID |
2. insert, update, delete 태그의 속성 기본 사용예시 -1 : parameterType
💡 insert, update, delete 태그의 속성 기본 사용예시
- 해당 예시에서는 parameterType만 명시하여 전달하려는 파라미터 객체나 타입을 지정합니다.
<insert id="insertCode" parameterType="codeDto">
INSERT INTO tb_code(grp_cd, cd, grp_cd_nm, cd_nm, sort_order, reg_dt, use_yn)
values ( #{grpCd}
, #{cd}
, #{grpCdNm}
, #{cdNm}
, #{sortOrder}
, #{regDt}
, #{useYn})
</insert>
<update id="updateCode" parameterType="codeDto">
UPDATE tb_code
SET cd_nm = #{cdNm}
WHERE cd = #{cd}
</update>
<update id="deleteCode" parameterType="codeDto">
UPDATE tb_code
WHERE cd = #{cd}
</update>
[ 더 알아보기 ]
💡 MyBatis에서 insert, update, delete 작업은 왜 결과값을 반환하지 않은가?
- 특정 '타입'의 객체를 반환하지 않기 때문에 resultType 속성을 지정할 필요가 없습니다. 이들 작업은 대신 성공적으로 수행된 행의 수를 반환합니다.
3. insert 태그의 속성 사용 예시 -2: useGeneratedKeys, keyProperty
💡 insert 태그의 속성 사용 예시 -2
- 해당 예시에서는 insert를 수행한 이후 Auto Increment 된 키 값을 다시 반환하기 위함입니다
-useGeneratedKeys:자동 생성된 키를 사용할지 여부
- keyProperty: 자동 생성된 키를 설정할 속성
<insert id="insertUser" useGeneratedKeys="true" keyProperty="userSq">
INSERT INTO tb_user(user_id, user_pw, user_nm, user_st)
VALUES (#{userId}, #{userPw}, #{userNm}, #{userSt})
</insert>
💡 [참고] 이를 이용한 예시에 대해 상세히 알고 싶으시면 아래의 글을 참고하시면 도움이 됩니다.
4. insert 태그의 속성 사용 예시 -3: selectKey 태그와 조합
💡 insert 태그의 속성 사용 예시 -2: selectKey
- insert 구문에 selectKey 태그를 포함하여서 insert의 트랜잭션 시작 전 후에 바로 수행할 수 있도록 구성할 수 있습니다.
<insert id="insertUser" parameterType="userDto">
<selectKey keyProperty="userSq" order="AFTER" resultType="int">
SELECT LAST_VALUE FROM public.tb_user_user_sq_seq
</selectKey>
INSERT INTO tb_user(user_id, user_pw, user_nm, user_st)
VALUES (#{userId}, #{userPw}, #{userNm}, #{userSt})
</insert>
💡 [참고] 이를 이용한 예시에 대해 상세히 알고 싶으시면 아래의 글을 참고하시면 도움이 됩니다.
오늘도 감사합니다. 😀
반응형