<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.itwill.mapper.MyUserMapper">
<insert id="insertUser" parameterType="MyUser">
insert into myuser values(#{userId}, #{userName})
</insert>
<!-- resultType 속성을 사용하면 resultType 속성값으로 설정된 클래스로 객체를 생성하여
검색행의 컬럼값을 같은 이름의 객체 필드값으로 자동 저장하여 제공 - 자동 매핑 -->
<!-- 문제점 : 검색행의 컬럼명과 resultType 속성값으로 설정된 클래스의 필드명이 모두 다른
경우 resultType 속성값으로 설정된 클래스의 객체 대신 NULL 제공 -->
<!--
<select id="selectUserList" resultType="MyUser">
select * from myuser order by user_id
</select>
-->
<!-- 해결방법-1 : 검색행의 컬럼명을 resultType 속성값으로 설정된 클래스의 필드명과 같도록 검색 -->
<!-- => SELECT 명령에서 Column Alias 기능을 이용하여 검색대상의 별칭을 필드명과 같도록 검색 -->
<!--
<select id="selectUserList" resultType="MyUser">
select user_id userId,user_name userName from myuser order by user_id
</select>
-->
<!-- sql : SQL 명령을 구성하는 일부분의 문장을 등록하기 위한 엘리먼트 -->
<!-- id 속성 : sql 엘리먼트의 식별자를 속성값으로 설정 -->
<sql id="myUserColumnAlias">
user_id userId,user_name userName
</sql>
<!-- include : sql 엘리먼트로 등록된 문장을 제공받아 SQL 명령에 포함하는 엘리먼트 -->
<!-- refid 속성 : sql 엘리먼트의 식별자를 속성값으로 설정 -->
<!--
<select id="selectUserList" resultType="MyUser">
select <include refid="myUserColumnAlias"/> from myuser order by user_id
</select>
-->
<!-- 해결방법-2 : mybatis 환경설정 파일(mybatis-config.xml)의 setting 엘리먼트를 사용하여
스네이크 표기법의 표현된 식별자를 자동으로 카멜 표기법으로 변환되도록 환경설정 변경 -->
<!--
<select id="selectUserList" resultType="MyUser">
select * from myuser order by user_id
</select>
-->
<!-- 해결방법-3 : resultMap 엘리먼트를 사용하여 검색행의 컬럼값이 클래스의 필드에 저장
되도록 설정 - 수동 매핑 -->
<!-- resultMap : 검색행을 Java 객체로 생성하여 제공하기 위한 엘리먼트 -->
<!-- => 검색행의 컬럼값을 필드에 저장하기 위해 하위 엘리먼트를 사용 -->
<!-- => 하위 엘리먼트 : constructor, id, result, association, collection, discriminator -->
<!-- type 속성 : resultMap 엘리먼트로 제공될 Java 객체의 자료형(클래스)을 속성값으로 설정 -->
<!-- => Java 자료형 대신 typeAlias 엘리먼트의 별칭 사용 가능 -->
<!-- id 속성 : resultMap 엘리먼트의 식별자를 속성값으로 설정 -->
<resultMap type="MyUser" id="myUserResultMap">
<!-- id : 검색행의 컬럼값을 필드에 저장하기 위한 엘리먼트 - Setter 메소드 호출 -->
<!-- => PK 제약조건이 설정된 컬럼값을 제공받아 필드에 저장하기 위해 사용 -->
<!-- column 속성 : 검색행의 컬럼명을 속성값으로 설정 -->
<!-- property 속성 : 클래스의 필드명을 속성값으로 설정 -->
<id column="user_id" property="userId"/>
<!-- result : 검색행의 컬럼값을 필드에 저장하기 위한 엘리먼트 - Setter 메소드 호출 -->
<result column="user_name" property="userName"/>
</resultMap>
<!-- resultMap 속성 : resultMap 엘리먼트의 식별자를 속성값으로 설정 - 수동 매핑 -->
<select id="selectUserList" resultMap="myUserResultMap">
select * from myuser order by user_id
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.itwill.mapper.MyReplyMapper">
<insert id="insertReply" parameterType="MyReply">
<selectKey resultType="int" keyProperty="replyNo" order="BEFORE">
select myreply_seq.nextval from dual
</selectKey>
insert into myreply values(#{replyNo},#{replyId},#{replyContent},sysdate,#{replyCommentNo})
</insert>
<select id="selectReplyList" resultType="MyReply">
select * from myreply order by reply_no desc
</select>
<!-- MYREPLY 테이블에 저장된 모든 댓글중에서 가장 최근에 작성된 5개의 댓글만 검색 -->
<!-- 문제점 : XML 기반의 매퍼 파일에서는 SQL 명령이 등록된 엘리먼트에서 관계 연산자
(> 또는 <)를 사용할 경우 엘리먼트를 표시하는 기호로 인식되어 에러 발생 -->
<!-- 해결법-1 : 관계 연산자(> 또는 <)를 엔티티 레퍼런스(회피문자)로 변경하여 SQL 명령 작성 -->
<!-- 해결법-2 : CDATA 세션을 사용하여 SQL 명령 작성 -->
<select id="selectCountReplyList" resultType="MyReply">
<!--
select rownum,reply.* from (select * from myreply
order by reply_no desc) reply where rownum <= 5
-->
<![CDATA[
select rownum,reply.* from (select * from myreply
order by reply_no desc) reply where rownum <= 5
]]>
</select>
<resultMap type="MyReplyUser" id="myReplyUserResultMap1">
<association property="reply" javaType="MyReply">
<id column="reply_no" property="replyNo"/>
<result column="reply_id" property="replyId"/>
<result column="reply_content" property="replyContent"/>
<result column="reply_date" property="replyDate"/>
<result column="reply_comment_no" property="replyCommentNo"/>
</association>
<association property="user" javaType="MyUser">
<id column="user_id" property="userId"/>
<result column="user_name" property="userName"/>
</association>
</resultMap>
<select id="selectReplyUserList1" resultMap="myReplyUserResultMap1">
select reply_no,reply_id,reply_content,reply_date,reply_comment_no,user_id,user_name
from myreply join myuser on reply_id=user_id order by reply_no desc
</select>
<resultMap type="MyReply" id="myReplyResultMap">
<id column="reply_no" property="replyNo"/>
<result column="reply_id" property="replyId"/>
<result column="reply_content" property="replyContent"/>
<result column="reply_date" property="replyDate"/>
<result column="reply_comment_no" property="replyCommentNo"/>
</resultMap>
<resultMap type="MyReplyUser" id="myReplyUserResultMap2">
<!-- reultMap 속성 : reultMap 엘리먼트의 식별자를 속성값을 설정 -->
<!-- => reultMap 엘리먼트로 설정된 매핑정보를 이용하여 검색행의 컬럼값을 객체 필드에
저장하여 객체를 제공받아 포함 객체의 필드에 저장 -->
<association property="reply" resultMap="myReplyResultMap"/>
<!-- select 속성 : select 엘리먼트의 식별자를 속성값으로 설정 -->
<!-- => select 엘리먼트의 SELECT 명령으로 실행된 검색결과를 객체로 제공받아 포함 객체 필드에 저장 -->
<!-- column 속성 : SELECT 명령으로 검색된 행의 컬럼명을 속성값으로 설정 -->
<!-- => SELECT 명령으로 검색된 행의 컬럼값을 select 속성값으로 설정된 select 엘리먼트
의 parameterType 속성값으로 전달하여 SQL 명령에서 사용 -->
<association property="user" select="selectMyUser" column="reply_id"/>
</resultMap>
<!-- association 엘리먼트에서만 사용하기 위한 SELECT 명령 등록 -->
<!-- => parameterType 속성으로 전달받은 값으로 단일행이 검색되도록 SELECT 명령 작성 -->
<!-- => DAO 클래스의 메소드에서 사용될 SQL 명령이 아니므로 Interface 기반의 맵퍼 파일에서
추상메소드 미선언 -->
<select id="selectMyUser" parameterType="string" resultType="MyUser">
select * from myuser where user_id=#{userId}
</select>
<!-- 테이블 조인을 사용하지 않고 resultMap 엘리먼트의 매핑정보를 제공받아 2개 이상의
테이블의 컬럼값을 검색하여 Java 객체로 제공 가능 -->
<select id="selectReplyUserList2" resultMap="myReplyUserResultMap2">
select * from myreply order by reply_no desc
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.itwill.mapper.MyCommentMapper">
<!-- cache : SELECT 명령의 검색결과를 임시 메모리(Cache Memory)에 저장하여 빠른 검색결과를
제공하기 위한 엘리먼트 - 가독성 증가 -->
<!-- => INSERT,UPDATE,DELETE 명령이 실행되면 임시 메모리에 저장된 검색결과는 자동 초기화 -->
<!-- => 검색결과를 저장하는 객체는 반드시 객체 직렬화 클래스로 작성 -->
<!-- <cache/> -->
<insert id="insertComment1" parameterType="MyComment1">
insert into mycomment values(mycomment_seq.nextval, #{commentId}, #{commentContent}, sysdate)
</insert>
<insert id="insertComment2" parameterType="MyComment1">
<!-- selectKey : SELECT 명령의 검색 결과값을 insert 엘리먼트의 parameterType 속성값으로
설정된 클래스의 필드값으로 저장하기 위한 엘리먼트 - insert 엘리먼트에 종속된 엘리먼트 -->
<!-- => 자동 증가값 또는 난수값을 SELECT 명령으로 검색하여 객체의 필드에 저장하여 INSERT 명령에서 사용하기 위해 작성 -->
<!-- resultType 속성 : SELECT 명령으로 검색된 결과값을 반환받기 위한 Java 자료형을 속성값으로 설정 -->
<!-- keyProperty 속성 : insert 엘리먼트의 parameterType 속성값으로 설정된 클래스의 필드명을 속성값으로 설정 -->
<!-- => SELECT 명령의 검색 결과값을 제공받아 Java 객체의 필드에 저장하기 위해 설정 -->
<!-- order 속성 : BEFORE 또는 AFTER 중 하나를 속성값으로 설정 -->
<selectKey resultType="int" keyProperty="commentNo" order="BEFORE">
select mycomment_seq.nextval from dual
</selectKey>
insert into mycomment values(#{commentNo}, #{commentId}, #{commentContent}, sysdate)
</insert>
<!-- resultType 속성을 사용하여 자동 매핑 기능으로 Java 객체 제공 -->
<!-- => 검색행의 컬럼명과 resultType 속성값으로 설정된 클래스의 필드명이 같도록 작성 -->
<select id="selectCommentList1" resultType="MyComment1">
select * from mycomment order by comment_no desc
</select>
<!-- 검색행의 컬럼명과 resultType 속성값으로 설정된 클래스의 필드명이 모두 다른 경우
resultType 속성값으로 설정된 클래스의 객체 대신 NULL 제공 -->
<!--
<select id="selectCommentList2" resultType="MyComment2">
select * from mycomment order by comment_no desc
</select>
-->
<!-- 검색행의 컬럼명을 resultType 속성값으로 설정된 클래스의 필드명과 같도록 Column Alias
기능을 사용하여 검색 - 컬럼의 별칭으로 사용하기 부적절한 단어는 "" 기호를 사용하여 표현 -->
<!--
<select id="selectCommentList2" resultType="MyComment2">
select comment_no no, comment_id id, comment_content content
,comment_date "date" from mycomment order by comment_no desc
</select>
-->
<!-- resultMap 엘리먼트를 이용하여 검색행의 컬럼값을 클래스의 필드에 저장되도록 설정하여 제공 -->
<!-- => type 속성값으로 설정된 Java 클래스의 기본 생성자로 객체를 생성하고 검색행의 컬럼값을
id 엘리먼트 또는 result 엘리먼트를 사용하여 객체의 Setter 메소드를 호출하여 필드값이 변경되도록 처리 -->
<resultMap type="MyComment2" id="myComment2ResultMap">
<id column="comment_no" property="no"/>
<result column="comment_id" property="id"/>
<result column="comment_content" property="content"/>
<result column="comment_date" property="date"/>
</resultMap>
<!-- select 엘리먼트의 resultMap 속성을 사용하여 검색행을 Java 객체로 수동 매핑하여 제공 -->
<!--
<select id="selectCommentList2" resultMap="myComment2ResultMap">
select * from mycomment order by comment_no desc
</select>
-->
<!-- constructor 엘리먼트를 사용하여 type 속성값으로 설정된 Java 클래스의 매개변수가
작성된 생성자로 객체를 생성하고 생성자 매개변수에 검색행의 컬럼값을 전달하여 객체의
필드에 저장되도록 매핑 처리 -->
<resultMap type="MyComment2" id="myComment2ConstructResultMap">
<!-- constructor : resultMap 엘리먼트의 type 속성값으로 설정된 Java 클래스의 생성자를
이용하여 매핑 처리하기 위한 정보를 제공하는 엘리먼트 -->
<!-- => 하위 엘리먼트 : idArg, arg -->
<!-- => 생성자 매개변수와 하위 엘리먼트의 갯수와 자료형이 동일해야만 매핑 가능 -->
<constructor>
<!-- idArg : 검색행의 컬럼값을 생성자 매개변수에 전달하기 위한 엘리먼트 -->
<!-- => PK 제약조건이 설정된 컬럼값을 제공받아 생성자 매개변수에 전달하기 위해 사용 -->
<!-- column 속성 : 검색행의 컬럼명을 속성값으로 설정 -->
<!-- javaType 속성 : 생성자 매개변수의 자료형을 속성값으로 설정 -->
<!-- => Java 자료형 대신 typeAlias 엘리먼트로 설정된 별칭 사용 가능 -->
<idArg column="comment_no" javaType="_int"/>
<!-- arg : 검색행의 컬럼값을 생성자 매개변수에 전달하기 위한 엘리먼트 -->
<arg column="comment_id" javaType="string"/>
<!--
<arg column="comment_content" javaType="string"/>
<arg column="comment_date" javaType="string"/>
-->
</constructor>
<!-- constructor 엘리먼트와 id 엘리먼트(result 엘리먼트)를 같이 사용하여 매핑 처리 가능 -->
<result column="comment_content" property="content"/>
<result column="comment_date" property="date"/>
</resultMap>
<select id="selectCommentList2" resultMap="myComment2ConstructResultMap">
select * from mycomment order by comment_no desc
</select>
<!--
<select id="selectCommentList3" resultType="MyComment3">
select comment_no "no",comment_id "id",user_name "name",comment_content "content"
,comment_date "date" from mycomment join myuser on comment_id=user_id
order by comment_no desc
</select>
-->
<resultMap type="MyComment3" id="myComment3ResultMap">
<id column="comment_no" property="no"/>
<result column="comment_id" property="id"/>
<result column="user_name" property="name"/>
<result column="comment_content" property="content"/>
<result column="comment_date" property="date"/>
</resultMap>
<select id="selectCommentList3" resultMap="myComment3ResultMap">
select comment_no,comment_id,user_name,comment_content,comment_date
from mycomment join myuser on comment_id=user_id order by comment_no desc
</select>
<select id="selectCommentUserList1" resultType="MyCommentUser1">
select comment_no,comment_id,comment_content,comment_date,user_id,user_name
from mycomment join myuser on comment_id=user_id order by comment_no desc
</select>
<!-- resultMap 엘리먼트의 type 속성값으로 설정된 클래스의 필드가 Java 객체를 저장하기 위한
필드로 선언된 경우 하위 엘리먼트로 association 엘리먼트를 사용하여 Java 객체를 제공받아
필드에 저장되도록 설정 -->
<resultMap type="MyCommentUser2" id="myCommentUser2ResultMap">
<!-- association : 1:1 관계의 테이블 조인에서 1개의 검색행을 Java 객체로 제공받아
필드에 저장되도록 매핑 처리하는 엘리먼트 - 포함관계 성립 -->
<!-- => id 엘리먼트와 result 엘리먼트를 하위 엘리먼트로 사용하여 검색행의 컬럼값이
포함 관계의 객체의 필드에 저장되도록 설정 -->
<!-- property 속성 : 포함 관계의 객체를 저장하기 위한 필드명을 속성값으로 설정 -->
<!-- javaType 속성 : 검색결과를 제공받기 위한 객체의 Java 자료형을 속성값으로 설정 -->
<!-- => Java 자료형 대신 typeAlias 엘리먼트로 설정된 별칭 사용 가능 -->
<association property="comment" javaType="MyComment1">
<id column="comment_no" property="commentNo"/>
<result column="comment_id" property="commentId"/>
<result column="comment_content" property="commentContent"/>
<result column="comment_date" property="commentDate"/>
</association>
<association property="user" javaType="MyUser">
<id column="user_id" property="userId"/>
<result column="user_name" property="userName"/>
</association>
</resultMap>
<select id="selectCommentUserList2" resultMap="myCommentUser2ResultMap">
select comment_no,comment_id,comment_content,comment_date,user_id,user_name
from mycomment join myuser on comment_id=user_id order by comment_no desc
</select>
<!-- 게시글번호를 전달받아 MYCOMMNET 테이블에 저장된 해당 게시글번호의 게시글을 검색하여
MyComment1 객체로 제공하는 엘리먼트 - 검색행 : 1개 -->
<select id="selectComment" parameterType="int" resultType="MyComment1">
select * from mycomment where comment_no=#{commentNo}
</select>
<!-- 게시글번호를 전달받아 MYREPLY 테이블에 저장된 해당 게시글번호의 댓글을 검색하여
MuReply 객체로 제공하는 엘리먼트 - 검색행 : 0개 이상 -->
<select id="selectCommentNoReplyList" parameterType="int" resultType="MyReply">
select * from myreply where reply_comment_no=#{replyCommentNo} order by reply_no desc
</select>
<!-- resultMap 엘리먼트의 type 속성값으로 설정된 클래스의 필드 자료형이 List인 경우
collection 엘리먼트를 사용하여 List 객체를 생성하여 필드에 저장되도록 설정 -->
<!-- resultMap 엘리리먼의 하위 엘리먼트 작성 순서 -->
<!-- => constructor, id, result, association, collection, discriminator -->
<!-- => association 엘리먼트가 resultMap 엘리먼트의 첫번째 하위 엘리먼트인 경우 내부적으로
selectOne 메소드를 사용하여 하나의 검색행에 대한 객체만 제공하여 필드에 저장 -->
<!-- 문제점)association 엘리먼트가 resultMap 엘리먼트의 첫번째 하위 엘리먼트인 경우 다수의
행이 검색된 경우 TooManyResultsException 발생 -->
<!-- 해결법)다수행을 검색할 경우 resultMap 엘리먼트의 첫번째 하위 엘리먼트를 association
엘리먼트가 아닌 다른 엘리먼트로 설정하여 매핑 처리 -->
<resultMap type="MyCommentReply" id="myCommentReplyResultMap">
<id column="comment_no" property="commentNo"/>
<association property="comment" javaType="MyComment1">
<id column="comment_no" property="commentNo"/>
<result column="comment_id" property="commentId"/>
<result column="comment_content" property="commentContent"/>
<result column="comment_date" property="commentDate"/>
</association>
<!-- collection: List 객체를 생성하여 포함 객체 필드에 저장하기 위한 엘리먼트 -->
<!-- => 1:N 관계의 테이블 조인에서 0개 이상의 검색행을 List 객체의 요소로 저장하여 생성 -->
<!-- => id 엘리먼트와 result 엘리먼트를 하위 엘리먼트로 사용하여 검색행의 컬럼값이
List 객체의 요소 필드에 저장되도록 설정 -->
<!-- property 속성 : resultMap 엘리먼트의 type 속성값으로 설정된 클래스의 필드명을 속성값으로 설정 -->
<!-- ofType 속성 : List 객체에 저장될 요소의 Java 자료형을 속성값으로 설정 -->
<!-- => Java 자료형 대신 typeAlias 엘리먼트로 설정된 별칭 사용 가능 -->
<collection property="replyList" ofType="MyReply">
<id column="reply_no" property="replyNo"/>
<result column="reply_id" property="replyId"/>
<result column="reply_content" property="replyContent"/>
<result column="reply_date" property="replyDate"/>
<result column="reply_comment_no" property="replyCommentNo"/>
</collection>
</resultMap>
<!-- 1:N 관계의 조인은 반드시 OUTER JOIN 사용하여 검색 -->
<!-- => 댓글이 없는 게시글을 검색하기 위해 LEFT OUTER JOIN 사용 -->
<select id="selectCommentReply" parameterType="int" resultMap="myCommentReplyResultMap">
select comment_no,comment_id,comment_content,comment_date,reply_no,reply_id
,reply_content,reply_date,reply_comment_no from mycomment left join
myreply on comment_no=reply_comment_no where comment_no=#{commentNo}
order by reply_no desc
</select>
<!--
<resultMap type="MyCommentReplyUser" id="myCommentReplyUserResultMap">
<id column="comment_no" property="commentNo"/>
<result column="comment_id" property="commentId"/>
<result column="comment_content" property="commentContent"/>
<result column="comment_date" property="commentDate"/>
<association property="user" javaType="MyUser">
<id column="user_id" property="userId"/>
<result column="user_name" property="userName"/>
</association>
<collection property="replyUserList" ofType="MyReplyUser">
<association property="reply" javaType="MyReply">
<id column="reply_no" property="replyNo"/>
<result column="reply_id" property="replyId"/>
<result column="reply_content" property="replyContent"/>
<result column="reply_date" property="replyDate"/>
<result column="reply_comment_no" property="replyCommentNo"/>
</association>
<association property="user" javaType="MyUser">
<id column="reply_user_id" property="userId"/>
<result column="reply_user_name" property="userName"/>
</association>
</collection>
</resultMap>
<select id="selectCommentReplyUser" parameterType="int" resultMap="myCommentReplyUserResultMap">
select comment_no,comment_id,comment_content,comment_date,user_id,user_name,reply_no
,reply_id,reply_content,reply_date,reply_comment_no,reply_user_id,reply_user_name
from mycomment join myuser on comment_id=user_id left join
(select reply_no,reply_id,reply_content,reply_date,reply_comment_no
,user_id reply_user_id,user_name reply_user_name from myreply join myuser
on reply_id=user_id) on comment_no=reply_comment_no
where comment_no=#{commentNo} order by reply_no desc
</select>
-->
<!-- autoMapping 속성 : false 또는 true 중 하나를 속성값으로 설정 -->
<!-- => autoMapping 속성값을 [true]로 설정한 경우 검색행의 컬럼명과 필드명 같은 경우 자동 매핑 처리 -->
<resultMap type="MyCommentReplyUser" id="myCommentReplyUserResultMap" autoMapping="true">
<id column="comment_no" property="commentNo"/>
<association property="user" javaType="MyUser" autoMapping="true"/>
<collection property="replyUserList" select="selectReplyUser" column="comment_no"/>
</resultMap>
<resultMap type="MyReplyUser" id="myReplyUserResultMap" autoMapping="true">
<association property="reply" javaType="MyReply" autoMapping="true"/>
<association property="user" javaType="MyUser" autoMapping="true"/>
</resultMap>
<select id="selectReplyUser" parameterType="int" resultMap="myReplyUserResultMap">
select reply_no,reply_id,reply_content,reply_date,reply_comment_no,user_id,user_name
from myreply join myuser on reply_id=user_id where reply_comment_no=#{replyCommentNo} order by reply_no desc
</select>
<select id="selectCommentReplyUser" parameterType="int" resultMap="myCommentReplyUserResultMap">
select comment_no,comment_id,comment_content,comment_date,user_id,user_name
,reply_no,reply_id,reply_content,reply_date,reply_comment_no
from mycomment join myuser on comment_id=user_id left join myreply on comment_no=reply_comment_no
where comment_no=#{commentNo} order by reply_no desc
</select>
</mapper>