라즈베리파이반

라즈베리파이 등 컴퓨터계열 게시판입니다.

제목스프링 레거시로 게시판 만들기 (2) : 매퍼 작성2022-10-22 00:30
작성자user icon Level 4
첨부파일mapper.zip (3.9KB)

88x31.png


1. 매퍼(mapper) 작성


매퍼(mapper)는 sqlSession을 통해서 repository에 해당하는 DAO에 SQL 쿼리문을 연결하여 실행합니다.


우선 매퍼를 작성하기 전에 테이블을 생성하겠습니다. 레거시에서는 DDL을 자동으로 작성해주지 않아서 수동으로 테이블을 만들어야합니다. DBeaver를 통해서 스키마를 생성해주세요.


테이블은 아래 ER모델을 참고하여 작성하겠습니다.



게시글을 저장하는 board, 댓글을 저장하는 comments, 게시글을 분류하는 category, 인증을 위한 member, 인가권한을 확인하기 위한 member_group로 구성합니다.


CREATE TABLE board (

document_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,

category_id INT NOT NULL,

is_notice CHAR(1) DEFAULT 'N',

title VARCHAR(250) NOT NULL,

content CLOB NOT NULL,

like_count INT DEFAULT 0,

dislike_count INT DEFAULT 0,

read_count INT DEFAULT 0,

member_id INT NOT NULL,

create_date DATE DEFAULT SYSDATE,

update_date DATE DEFAULT SYSDATE

);


CREATE TABLE comments (

comment_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,

document_id INT NOT NULL,

content CLOB,

like_count INT DEFAULT 0,

dislike_count INT DEFAULT 0,

member_id INT NOT NULL,

create_date DATE DEFAULT SYSDATE,

update_date DATE DEFAULT SYSDATE

);


CREATE TABLE category (

category_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,

category VARCHAR(80) UNIQUE NOT NULL,

create_date DATE DEFAULT SYSDATE,

update_date DATE DEFAULT SYSDATE

);


CREATE TABLE MEMBER (

member_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,

password VARCHAR(60) NOT NULL,

email VARCHAR(250) UNIQUE,

name VARCHAR(40) NOT NULL,

nick_name VARCHAR(40) UNIQUE NOT NULL,

group_id INT NOT NULL,

create_date DATE DEFAULT SYSDATE,

last_login DATE DEFAULT SYSDATE

);


CREATE TABLE member_group (

group_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,

group_name VARCHAR(80) UNIQUE NOT NULL,

create_date DATE DEFAULT SYSDATE,

update_date DATE DEFAULT SYSDATE

);


ALTER TABLE board ADD CONSTRAINT fk_category_id FOREIGN KEY(category_id) REFERENCES category(category_id);

ALTER TABLE board ADD CONSTRAINT fk_member_id FOREIGN KEY(member_id) REFERENCES member(member_id);


ALTER TABLE comments ADD CONSTRAINT fk_document_id FOREIGN KEY(document_id) REFERENCES board(document_id);

ALTER TABLE comments ADD CONSTRAINT fk_member_id_2 FOREIGN KEY(member_id) REFERENCES member(member_id);


ALTER TABLE member ADD CONSTRAINT fk_group_id_2 FOREIGN KEY(group_id) REFERENCES member_group(group_id);


이제 매퍼를 작성하겠습니다.


매퍼를 작성하기 전에 DBeaver를 통해 미리 쿼리를 작성해보도록 하겠습니다. 외래키를 통해 제약조건을 설정했기때문에 우선 그룹을 생성합니다.


Admin 그룹 생성 

INSERT INTO member_group (group_name) VALUES ('Admin');


쿼리문을 토대로 groupMapper를 생성합니다. 저번 글에서 생성한 mappers 패키지 아래 groupMapper.xml 파일을 만들고 다음과 같이 CRUD 쿼리를 작성하세요.


groupMapper.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="kro.rubisco.dao.GroupDAO">


<insert id="create">

insert into member_group (group_name) values (#{groupName})

</insert>


<select id="read" resultType="GroupDTO">

select * from member_group where group_id = #{groupId}

</select>


<update id="update">

update member_group set group_name=#{groupName}, update_date=SYSDATE 

where group_id = #{groupId}

</update>


<delete id="delete"> delete from member_group where group_id = #{groupId} </delete>


<select id="listAll" resultType="GroupDTO">

<![CDATA[ select * from member_group where group_id > 0 order by group_id desc ]]>

</select>


</mapper>


JPA에서는 레포지토리를 통해 SQL문 없이도 DB연결이 쉽지만, Mybatis는 SQL문을 직접 작성해야합니다.


우선 mapper 태그에 namespace 속성을 통해 DAO에 연결해줍니다. DAO는 Data Access Object의 약자로, 데이터베이스와 연결되는 객체입니다. JPA에서 Repository와 같은 역할을 합니다. DAO가 mapper에 연결되면서 SQL문을 실행시키고, select문의 경우 Entity를 생성합니다. mapper 태그 하위 태그에는 DML이 들어가며, id 속성값은 DAO의 메소드명이 됩니다.


resultType 속성은 Entity를 DTO에 연결해줍니다. DTO는 Data Transfer Object의 약자로, 데이터를 전송해주는 객체입니다. 


DTO 객체의 멤버변수는 #{멤버변수}로 표시합니다. listAll 메소드에서 <![CDATA[...]]>라고 표시한 것은 꺽쇠 표시(>) 때문입니다. 해당 태그로 감싸지 않으면 꺽쇠가 태그를 내타내는 기호인지 부등호를 나타내는 기호인지 알 수 없기때문에 오류를 나타냅니다.


자바에서는 관례적으로 변수명을 낙타표기법(Camel Case)으로 나타냅니다. table과 column을 스네이크 표기법(Snake Case)으로 만들었기 때문에 DTO 변수의 매핑을 위해 이를 변환할 필요가 있습니다.


mybatis-config.xml 파일의 configuration 태그 아래에 다음과 같이 settings 태그를 추가합니다.


mybatis-config.xml 

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration 

PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 

"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>


<settings>


<!-- 카멜 케이스 매핑 설정 --> 

<setting name="mapUnderscoreToCamelCase" value="true"/>


<!-- 쿼리 결과 필드가 null인 경우, 누락되지 않도록 설정 --> 

<setting name="callSettersOnNulls" value="true"/>


<!-- 쿼리에 보내는 파라미터가 null인 경우, 오류가 발생하는 것을 방지 --> 

<setting name="jdbcTypeForNull" value="NULL"/>


</settings>


<typeAliases>

<package name="kro.rubisco.dto"/>

</typeAliases>

</configuration>


이제 나머지 매퍼도 만들어줍니다. memberMapper부터 만들겠습니다.


memberMapper.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="kro.rubisco.dao.MemberDAO">


<resultMap id="getMember" type="MemberDTO">

<association property="group" column="group_id" javaType="GroupDTO" select="getGroup" />

</resultMap>


<insert id="create">

insert into member (password, email, name, nick_name, group_id)

values (#{password}, #{email}, #{name}, #{nickName}, #{groupId})

</insert>


<select id="read" resultMap="getMember">

select m.* from member m join member_group g on m.group_id = g.group_id where member_id = #{memberId}

</select>


<select id="getGroup" resultType="GroupDTO">

select * from member_group where group_id=#{groupId}

</select>


<update id="update">

update member 

set password=#{password},

email=#{email}, 

name=#{name}, 

nick_name= #{nickName},

where member_id = #{memberId}

</update>


<delete id="delete"> delete from member where member_id = #{memberId} </delete>


<select id="listAll" resultMap="getMember">

<![CDATA[ 

select m.* from member m 

join member_group g on m.group_id = g.group_id 

where m.member_id > 0 order by m.member_id desc 

]]>

</select>


</mapper>


resultMap 이라는 태그가 추가되었습니다. select문의 경우 검색된 entity를 resultType에 지정된 타입의 객체에 담게 되는데, colmun은 원시값을 가지기 때문에 객체에 참조변수가 있다면 매핑하지 않습니다. 그러므로 연관관계를 통해 entity 자체를 객체에 담기 위해서는 resultMap을 설정하여 매핑정보를 입력해주면 됩니다.


resultMap 태그에 id를 설정하고 type 속성에 매핑되는 객체 타입을 입력합니다. 하위 태그인 association은 1:N 연관관계를 설정할 수 있습니다. property 속성에는 resultMap의 type에서 연관관계를 맺을 매개변수명을 입력합니다.


아래 코드로 예를 들어보겠습니다.


resultMap 설정 

<resultMap id="getMember" type="MemberDTO">

<association property="group" column="group_id" javaType="GroupDTO" select="getGroup" />

</resultMap>


<select id="read" resultMap="getMember">

select m.* from member m join member_group g on m.group_id = g.group_id where member_id = #{memberId}

</select>


<select id="getGroup" resultType="GroupDTO">

select * from member_group where group_id=#{groupId}

</select>


id가 read인 select 태그에 resultType 속성 대신에 resultMap 속성을 추가합니다. 해당 select문을 실행시켜 출력된 entity는 resultMap의 type속성에 입력한 MemberDTO 타입에 매핑됩니다. 이때 association 태그의 select 속성에 입력된 getGroup select문을 함께 실행시켜 검색된 결과는 javaType 속성에 입력된 GroupDTO 타입에 매핑되고, 해당 객체는 property에 입력된 group 매개변수가 참조합니다. column 속성에는 getGroup select문을 실행시킬 때 매개변수가 되는 column을 입력합니다.


동일한 방식으로 각각의 mapper를 만들어줍시다.


categoryMapper.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="kro.rubisco.dao.CategoryDAO">


<insert id="create">

insert into category (category) values (#{category})

</insert>


<select id="read" resultType="CategoryDTO">

select * from category where category_id = #{categoryId}

</select>


<update id="update">

update category set category=#{category}, update_date=SYSDATE 

where category_id = #{categoryId}

</update>


<delete id="delete"> delete from category where category_id = #{categoryId} </delete>


<select id="listAll" resultType="CategoryDTO">

<![CDATA[ select * from category where category_id > 0 order by category_id desc ]]>

</select>


</mapper>


boardMapper.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="kro.rubisco.dao.BoardDAO">


<resultMap id="getBoard" type="BoardDTO">

<id property="documentId" column="document_id" />

<association property="category" column="category_id" javaType="CategoryDTO" select="getCategory" />

<association property="member" column="member_id" javaType="MemberDTO" select="getMember" />

<association property="group" column="group_id" javaType="GroupDTO" select="getGroup" />

<collection property="commentList" column="document_id" javaType="java.lang.ArrayList" ofType="CommentDTO" select="getComments" />

</resultMap>


<select id="getCategory" resultType="CategoryDTO">

select * from category where category_id=#{categoryId}

</select>


<select id="getMember" resultType="MemberDTO">

select * from member where member_id=#{memberId}

</select>


<select id="getGroup" resultType="GroupDTO">

select * from member_group where group_id=#{groupId}

</select>


<select id="getComments" resultType="CommentDTO">

select * from comments where document_id=#{documentId}

</select>


<insert id="create">

insert into board (category_id, is_notice, title, content, member_id)

values (#{categoryId}, #{isNotice}, #{title}, #{content}, #{memberId})

</insert>


<select id="read" resultMap="getBoard"> 

select b.* from board b

join category c on b.category_id = c.category_id 

join member m on b.member_id = m.member_id

left outer join comments cmt on b.document_id = cmt.document_id

where b.document_id = #{documentId}

</select>


<update id="update">

update board 

set category_id=#{categoryId}, 

is_notice=#{isNotice}, 

title=#{title}, 

content=#{content},  

update_date=SYSDATE

where document_id = #{documentId}

</update>


<delete id="delete"> delete from board where document_id = #{documentId} </delete>


<select id="listAll" resultMap="getBoard">

<![CDATA[ 

select b.* from board b

join category c on b.category_id = c.category_id 

join member m on b.member_id = m.member_id

left outer join comments cmt on b.document_id = cmt.document_id

where b.document_id > 0 order by b.document_id desc

]]>

</select>


</mapper>


commentMapper.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="kro.rubisco.dao.CommentDAO">


<resultMap id="getComment" type="CommentDTO">

<association property="board" column="document_id" javaType="BoardDTO" select="getBoard" />

<association property="member" column="member_id" javaType="MemberDTO" select="getMember" />

</resultMap>


<select id="getBoard" resultType="BoardDTO">

select * from board where document_id=#{documentId}

</select>


<select id="getMember" resultType="MemberDTO">

select * from member where member_id=#{memberId}

</select>


<insert id="create">

insert into comments (document_id, content, member_id) 

values (#{documentId}, #{content}, #{memberId})

</insert>


<select id="read" resultMap="getComment">

select cmt.* from comments cmt

join board b on cmt.document_id = b.document_id 

join member m on cmt.member_id = m.member_id

where cmt.comment_id = #{commentId}

</select>


<update id="update">

update comments 

set document_id=#{documentId}, 

content=#{content}, 

update_date=SYSDATE

where comment_id = #{commentId}

</update>


<delete id="delete"> delete from comments where comment_id = #{commentId} </delete>


<select id="listAll" resultMap="getComment">

<![CDATA[ 

select cmt.* from comments cmt

join board b on cmt.document_id = b.document_id 

join member m on cmt.member_id = m.member_id

where comment_id > 0 order by comment_id desc

]]>

</select>


</mapper>

#스프링 레거시# mapper
댓글
자동등록방지
(자동등록방지 숫자를 입력해 주세요)