mybatis의 가장 중요한 목적 중 하나는 DAO로부터 SQL 문을 분리하는 것이다. 이렇게 분리된 SQL문은 SqlSession에서 사용한다. 다음 코드는 전 포스팅에 작성한 SQL 맵퍼 파일이다.
📌SQL mapper
MySqlProjectDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="spms.dao.ProjectDao">
<resultMap type="project" id="projectResultMap">
<id column="PNO" property="no" />
<result column="PNAME" property="title" />
<result column="CONTENT" property="content" />
<result column="STA_DATE" property="startDate"
javaType="java.sql.Date" />
<result column="END_DATE" property="endDate"
javaType="java.sql.Date" />
<result column="STATE" property="state" />
<result column="CRE_DATE" property="createdDate"
javaType="java.sql.Date" />
<result column="TAGS" property="tags" />
</resultMap>
<select id="selectList" resultMap="projectResultMap">
select PNO, PNAME, STA_DATE, END_DATE, STATE
from PROJECTS
order by PNO desc
</select>
<insert id="insert" parameterType="project">
insert into
PROJECTS(PNAME,CONTENT,STA_DATE,END_DATE,STATE,CRE_DATE,TAGS)
values
(#{title},#{content},#{startDate},#{endDate},0,now(),#{tags})
</insert>
<select id="selectOne" parameterType="int"
resultMap="projectResultMap">
select PNO, PNAME, CONTENT, STA_DATE, END_DATE, STATE, CRE_DATE, TAGS
from PROJECTS
where PNO=#{value}
</select>
<update id="update" parameterType="project">
update PROJECTS set
PNAME=#{title},
CONTENT=#{content},
STA_DATE=#{startDate},
END_DATE=#{endDate},
STATE=#{state},
TAGS=#{tags}
where PNO=#{no}
</update>
<delete id="delete" parameterType="int">
delete from PROJECTS
where PNO=#{value}
</delete>
</mapper>
💡<mapper> 루트 엘리먼트
namespace속성: Java의 패키지처럼 SQL문을 묶는 용도로 사용한다. 맵퍼 파일에 작성하는 모든 SQL문은 <mapper>태그에 놓인다.
<mapper namespace="spms.dao.ProjectDao">
...
</mapper>
💡<select>, <insert>, <update>, <delete> 엘리먼트
SQL문을 작성할 때 명령어에 따라 사용하는 태그가 다르다.
태그명만 봐서도 알겠지만 각각 SELECT, INSERT, UPDATE, DELETE문이다. 여기서 DELETE문은 <insert> 태그에 작성하더라도 문제는 없다. 하지만 유지보수를 위해서라도 맞는 태그를 사용하는 것이 좋다.
id 속성
SQL문을 작성할 때 각각의 SQL문을 구분하기 위해 id 속성을 사용한다.
resultType 속성
SELECT문을 실행하면 결과가 생성되는데 이 결과를 담을 객체를 지정하는 속성이 resultType이다.
<select id="selectList" resultType="spms.vo.Project">
위 코드처럼 resultType에는 클래스 이름(패키지 이름 포함)이 온다.
※만약 mybatis 설정 파일(mybatis-config.xml)에서 spms.vo.Project에 대한 별칭이 정의되어 있다면 resultType의 값으로 그 별칭을 사용할 수 있다.
<!-- mybatis 설정 파일 -->
<typeAliases>
<typeAlias type="spms.vo.Project" alias="project" />
</typeAliases>
<!-- SQL 맵퍼 파일 -->
<select id="selectList" resultType="project">
column과 setter 메소드
mybatis는 SELECT문의 결과를 저장할때 resultType에 선언된 클래스의 인스턴스를 생성하여 저장한다 하였다. 저장할 때 각 칼럼에 대응하는 setter 메소드를 찾아서 호출하여 인스턴스에 저장한다. 이때 setter 메소드는 대소문자 구분없이 set을 뺀 메소드의 이름과 컬럼 이름이 같으면 된다. 만약 컬럼의 이름과 일치하는 setter 메소드가 없다면, 해당 컬럼의 값은 인스턴스에 저장되지 않는다. 물론 테이블의 컬럼명과 객체의 변수명이 다른 경우 이런 일이 발생하지만(정확히는 setter 메소드) 이런 경우 해결하는 방법을 알아야 한다.
이 문제를 해결하는 방법은 SELECT문을 작성할 때 컬럼에 별칭을 붙이면 된다. 하지만 이렇게 별명을 붙이는 방식은 번거로울 것이다. 컬럼에 별명을 붙이는 대신 <resultMap>을 이용하면 컬럼 이름과 setter 메소드의 이름의 불일치 문제를 해결할 수 있다.
<resultMap> 엘리먼트
<resultMap type="project" id="projectResultMap">
<id column="PNO" property="no" />
<result column="PNAME" property="title" />
<result column="CONTENT" property="content" />
<result column="STA_DATE" property="startDate" javaType="java.sql.Date" />
<result column="END_DATE" property="endDate" javaType="java.sql.Date" />
<result column="STATE" property="state" />
<result column="CRE_DATE" property="createdDate" javaType="java.sql.Date" />
<result column="TAGS" property="tags" />
</resultMap>
- <resultMap> 태그의 자식 태그인 <result> 태그는 컬럼과 연결될 setter 메소드를 정의한다.
- column 속성: 컬럼 이름 / property 속성: 객체의 프로퍼티 이름
- PNAME 컬럼 값을 setTitle() 메소드와 연결시킨 것이다.
- <resultMap> 태그의 type 값은 컬럼 데이터를 저장할 클래스 이름 또는 클래스의 별칭이다. 만약 클래스 별칭으로 지정하려면 mybatis 설정 파일에 정의되어 있어야 한다. 우리는 위에서 'spms.vo.Project 클래스를 project라고 별칭을 지정하였기 때문에 위와 같이 type은 'project'라는 별칭으로 지정하여도 된다.
- <result>에서 javaType을 사용하면, 컬럼의 값을 특정 Java 객체로 변환할 수 있다.
- STA_DATE 컬럼에 대해 javaType을 java.sql.Date로 설정하면, 컬럼 값을 꺼낼 때 그 객체로 변환된다.
- 만일 javaType속성을 지정하지 않는다면, setter 매개변수 타입에 맞추어 컬럼 값이 변환된다.
- ※ java.util.Date 타입의 값은 외국 날짜 형식으로 출력되고
java.sql.Date 타입은 한국 날짜 형식으로 출력된다.
- <id> 엘리먼트는 <result> 태그와 작성 방법이 같다. 다른점은 <id> 태그에서 지정한 프로퍼티는 객체 식별자로 사용된다. SELECT 문을 실행하면 레코드 값을 저장하기 위해 결과 객체가 생성되는데, SELECT 문을 실행할 때마다 매번 결과 객체를 생성한다면 실행 성능이 나빠질 것이다. 이를 해결하기 위해 SELECT를 통해 생성된 결과 객체들은 별도의 보관소에 저장(캐싱)해두고, 다음 SELECT를 실행할 때 재사용한다. 이때 보관소에 저장된 객체를 구분하는 값으로 <id>에서 지정한 프로퍼티를 사용한다.
- <id column="PNO" property="no"/>
즉 위에 예시로 들은 코드를 살펴보면, 캐시에 보관된 객체들을 찾을 때 no 프로퍼티를 사용하도록 설정한 것이다. - 이에 관한 것은 아래에 추가적으로 설명하였다.
- <id column="PNO" property="no"/>
💡SQL 문의 입력 매개변수 처리
mybatis에서는 입력 매개변수를 #{프로퍼티명}으로 표시한다.
이때 #{프로퍼티명}이 가리키는 값은 <insert>의 parameterType에 지정한 객체의 프로퍼티 값(getter 메소드의 반환값)이다.
📌mybatis의 SELECT 결과 캐싱(caching)
SELECT를 실행할 때마다 결과 레코드에 대해 매번 객체를 생성한다면, 속도도 느리고 메모리도 낭비된다. 이를 개선하기 위해 mybatis는 객체 캐싱을 제공한다. 즉 한 번 생성된 객체는 버리지 않고 보관해 두었다가, 다음 SELECT를 실행할 때 재사용 한다. 이때 의 를 사용하여 식별자로 사용할 프로퍼티를 지정할 수 있다. 이렇게 지정하면 캐싱된 객체를 더욱 빨리 찾을 수 있다.
예를 들어 설명해보도록 하겠다.
첫 번째 SELECT를 실행하고 수행된 결과 객체는 풀(Pool)에 보관한다. 두 번째 질의가 들어왔을 때 새로 객체를 생성하기 전에, 풀(Pool)에 보관된 객체 중 <id> 태그로 지정한 프로퍼티 값과 일치하는 객체를 먼저 찾는다. 있다면 기존 객체를 사용하고 없다면 새로 객체를 생성한다.
'MyBatis' 카테고리의 다른 글
MyBatis 동적 SQL 사용 (예시. 항목 별 정렬) (0) | 2022.07.21 |
---|---|
[mybatis] mybatis 설정 파일 (0) | 2022.07.21 |
[mybatis] mybatis 적용 (0) | 2022.07.20 |
[mybatis] mybatis(마이바티스)란? (mybatis 환경세팅) (0) | 2022.07.20 |
퍼시스턴스 프레임워크(Persistence Framework)란? (0) | 2022.07.19 |