[ MyBatis3 ] SQL Map XML 파일(resultMap-2)

* id , result

<id property ="id" column="post_id" />

<result property="subject" column="post_subject" />


>> 결과 매핑의 기본적인 형태, id와 result 모두 한개의 칼럼을 한개의 프로퍼티나 간단한 데이터 타입의 필드에 매핑한다.


* constructor


<constructor>

<idArg column="id" javaType="int"/>

<arg column="username" javaType="String" />

</constructor>


- 프로퍼티가 데이터전송객체(DTO) 타입 클래스로 작동한다.

- MyBatis는 private 프로퍼티와 private 자바빈 프로퍼티를 지원하지만 많은 사람들은 생성자 주입을 선호한다.


* association

<association property="author" column="blog_author_id" javaType='Author">

<id property="id" column="author_id" />

<result property="username" column="author_username"/>

</association>


- association 요소는 "has-one" 타입의 관계를 이룬다.

- association 매핑은 다른 결과와 작동한다. 값을 가져오기 위해 대상 프로퍼티를 명시한다.

- MyBatis는 관계를 정의하는 두가지 방법을 제공한다.

  • 내포된(Nested) Select : 복잡한 타입을 리턴하는 다른 매핑된 SQL구문을 실행하는 방법
  • 내포된(Nested) Result : 조인된 결과물을 반복적으로 사용하여 내포된 결과매핑을 사용하는 방법

- 관계를 위한 내포된 Select

<resultMap id ="blogResult" type="Blog">

<association property ="author" column ="blog_author_id" javaType = "Author" select="selectAuthor" />

</resultMap>


<select id="selectBlog" parameterType ="int" resultMap="blogResult">

SELECT * FROM ……..

</select>


<select id= "selectAuthor: parameterType="int" resultType="Author">

SELECT * FROM …….

</select>


>> 두개의 select 구문중 하나는 Blog를 로드하고 다른하나는 Author를 로드한다.

Blog의 resultMap은 author 프로퍼티를 로드하기 위해 "selectAuthor" 구문을 사용한다.

다른 프로퍼티들은 칼럼과 프로퍼티명에 일치하는 것들로 자동으로 로드 될 것이다.


이 방법은 간단한 반면, 큰 데이터나 목록에는 제대로 작동하지 않을 것이다.

이 방법은 "N +1 Select문제"으로 알려진 문제점을 가진다.

- 레코드의 목록을 가져오기 위해 하나의 sql구문을 실행한다.("+1"에 해당)

- 리턴된 레코드별로, 각각의 상세데이터를 로드하기 위해 select구문을 실행한다.("N"에 해당)


- 관계를 위한 내포된 Result


<select id ="selectBlog" parameterType="int" resultMap="blogResult">

select

B.id as blog_id,

B.title as blog_title,

B.author_id as blog_author_id.

A.id as author_id,

A.username as author_username,

A.bio as author_bio

from Blog B left outer join Author A on B.author_id = A.id

where B.id = #{id}

</select>


<resultMap id="blogResult" type="Blog">

<id property ="blog_id" column="id" />

<result property="title" column="blog_title" />

<association property ="author" column="blog_author_id" javaType ="Author" resultMap="authorResult" />

</resultMap>


<resultMap id="authorResult" type="Author">

<id property="id" column="author_id" />

<result property="username" column="author_user_name" />

<result property="bio" author_id = "author_bio" />

</resultMap>


>> id 요소는 내포된 결과 매핑에서 매우 중요한 역할을 담당한다.

결과중 유일한 것을 찾아내기 위한 한개 이상의 프로퍼티를 명시해야 한다.

가능하면 결과중 유일한 것을 찾아낼수 있는 프로퍼티를 선택해야 한다

[ MyBatis3 ] SQL Map XML 파일(resultMap)

# resultMap

- MyBatis에서 가장 중요하고 강력한 요소이다. ResultSet에서 데이터를 가져올 때 작성되는 JDBC코드를 대부분 줄여주는 역할을 담당한다.

- 모든 칼럼의 값이 결과가 되는 간단한 구문에서는 HashMap에서 키 형태로 자동으로 매핑된다, 하지만 대부분의 경우 HashMap은 매우 좋은 도메인 모델이 되지는 못한다.

- 그래서 대부분 도메인모델로는 자바빈이나 POJO를 사용할 것이다.

- TypeAliases가 편리한 기능임을 기억해두는게 좋다. TypeAliases를 사용하면 타이핑 수를 줄일 수 있다.
<typeAlias type="com.someapp.model.User" alias="User"/>

<select id ="selectUsers" parameterType="int" resultType="User">
</select>

- 칼럼명이 프로퍼티명과 다르다면
  1. SQL 구문에 별칭을 지정

    <select id ="selectUsers" parameterType ="int" resultType ="User">
    select
    user_id as "id"
    user_name as "userName"
    from some_table
    </select>


  2. 명시적인 resultMap을 선언하는 방법

    <resultMap id ="userResultMap" type="User">
    <id property ="id" column="user_id" />
    <result property ="username" column="username" />
    </resultMap>

    <select id = "selectUsers" parameterType ="int" resultType ="userResultMap">
    select user_id, user_name
    from some_table
    </select>

- resultMap요소는 많은 하위 요소를 가진다. 다음은 resultMap요소의 개념적인 뷰이다.

  • constructor - 인스턴스화 되는 클래스의 생성자에 결과를 삽입하기 위해 사용
  • id - ID 결과, ID와 같은 결과는 전반적으로 성능을 향상시킴
  • result - 필드나 자바빈 프로퍼티에 삽입되는 일반적인 결과
  • association - 복잡한 타입의 연관관계; 많은 결과는 타입으로 나타난다.
  • collection - 복잡한 타입의 컬렉션
  • discriminator - 사용할 resultMap을 판단하기 위한 결과값을 사용

> 가장 좋은 형태는 매번 resultMap을 추가해서 빌드한다.

[ MyBatis3 ] SQL Map XML 파일(select, insert, update, delete, sql)

MyBatis의 가장 큰 장점은 매핑된 구문이다. 동일한 기능의 JDBC코드와 비교하면 아마도 95%이상 코드수가 감소하기도 한다.


# Select

- select 구문은 가장 많이 쓰는 요소이다. MyBatis는 데이터를 조회하고 그 결과를 매핑하는데 집중하고 있다.
  • MyBatis
<select id ="selectPerson" parameterType = "int" resultType = "hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>

  • JDBC
String selectPerson = "SELECT * FROM PERSON WHERE ID = ?";
PreparedStatement ps = comm.prepareStatment(selectPerson);
ps.setInt(1,id);

# insert, update, delete

* insert
<insert id ="insertAuthor" parameterType="domain.blog.Author">
insert into Author (id, username, password, email, bio)
values (#{id}, #{username}, #{password}, #{email}, #{bio})
</insert>
* update
<update id = "updateAuthor" parameterType="domain.blog.Author">
update Author set
username = #{username}
password =#{password}
email = #{email}
bio = #{bio}
where id = #{id}
</update>
* delete
<delete id = "deleteAuthor" parameterType="int">
delete from Author where id = #{id}
</delete>

* insert 자동생성키 설정(Autoincrement)

- 사용하는 데이터베이스가 자동생성키를 지원하는 경우
<insert id ="insertAuthor" parameterType="domain.blog.Author"
useGeneratedKeys = "true" keyProperty ="id">

- 자동생성키를 지원하지 않는 경우 (랜덤 ID 생성 -> 자동생성키와 비슷한 효과를 나타냄)
<insert id ="insertAuthor" parameterType="domain.blog.Author">
<selectKey keyProperty = "id" resultType ="int' order = "BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
</selectKey>

# Sql

- 이 요소는 다른 구문에서 재사용 가능한 SQL구문을 정의할 때 사용

<sql id = "userColumns">id, username, password</sql>

<select id = "selectUsers" parameterType ="int' resultType ="hashmap">
select <include refid = "userColumns"/>
from some_table
where id = #{id}
</select>


※ 출처 : Mybatis-3-User-Guide.pdf