create table mycomment(comment_no number primary key, comment_id varchar2(50)
, comment_content varchar2(100), comment_date date);
create sequence mycomment_seq;
이름 널? 유형
--------------- -------- -------------
COMMENT_NO NOT NULL NUMBER - 게시글 번호
COMMENT_ID VARCHAR2(50) - 게시글 작성자(아이디)
COMMENT_CONTENT VARCHAR2(100) - 게시글 내용
COMMENT_DATE DATE - 게시글 작성일
테이블의 컬럼명을 같은 이름의 필드로 선언하여 클래스 작성 (환경설정 파일에 의해 컬럼명과 필드명 동일)
XML 기반의 매퍼 파일에서 cache 엘리먼트를 사용한 경우 SELECT 명령에 대한 검색결과로 제공될 객체의 클래스는 반드시 객체 직렬화 클래스로 선언
package xyz.itwill.dto;
import java.io.Serializable;
public class MyComment1 implements Serializable {
private static final long serialVersionUID = -7534009978055893003L;
private int commentNo;
private String commentId;
private String commentContent;
private String commentDate;
public MyComment1() {
// TODO Auto-generated constructor stub
}
public int getCommentNo() {
return commentNo;
}
public void setCommentNo(int commentNo) {
this.commentNo = commentNo;
}
public String getCommentId() {
return commentId;
}
public void setCommentId(String commentId) {
this.commentId = commentId;
}
public String getCommentContent() {
return commentContent;
}
public void setCommentContent(String commentContent) {
this.commentContent = commentContent;
}
public String getCommentDate() {
return commentDate;
}
public void setCommentDate(String commentDate) {
this.commentDate = commentDate;
}
}
테이블의 컬럼명과 다른 이름의 필드를 선언하여 클래스 작성
매개변수가 작성된 생성자를 생성(필드 생성자 초기화 → 매개변수로 초기값 설정)하여 XML 매퍼파일에서 매핑 시 사용 가능
package xyz.itwill.dto;
public class MyComment2 {
private int no;
private String id;
private String content;
private String date;
public MyComment2() {
// TODO Auto-generated constructor stub
}
public MyComment2(int no, String id) {
super();
this.no = no;
this.id = id;
}
public MyComment2(int no, String id, String content, String date) {
super();
this.no = no;
this.id = id;
this.content = content;
this.date = date;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
package xyz.itwill.dto;
public class MyComment3 {
private int no;
private String id;
private String name;
private String content;
private String date;
public MyComment3() {
// TODO Auto-generated constructor stub
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
MYCOMMENT 테이블과 MYUSER 테이블의 검색결과를 저장하기 위한 클래스
package xyz.itwill.dto;
public class MyCommentUser1 {
//MYCOMMENT 테이블(게시글정보)의 검색결과를 저장하기 위한 필드 - 검색행 1개
private int commentNo;
private String commentId;
private String commentContent;
private String commentDate;
//MYUSER 테이블(회원정보)의 검색결과를 저장하기 위한 필드 - 검색행 1개
private String userId;
private String userName;
public MyCommentUser1() {
// TODO Auto-generated constructor stub
}
public int getCommentNo() {
return commentNo;
}
public void setCommentNo(int commentNo) {
this.commentNo = commentNo;
}
public String getCommentId() {
return commentId;
}
public void setCommentId(String commentId) {
this.commentId = commentId;
}
public String getCommentContent() {
return commentContent;
}
public void setCommentContent(String commentContent) {
this.commentContent = commentContent;
}
public String getCommentDate() {
return commentDate;
}
public void setCommentdate(String commentDate) {
this.commentDate = commentDate;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
MYCOMMENT 테이블과 MYUSER 테이블의 검색결과를 저장하기 위한 클래스
MYCOMMENT 테이블(게시글정보)의 검색결과를 저장하기 위한 필드
package xyz.itwill.dto;
public class MyCommentUser2 {
//MYCOMMENT 테이블(게시글정보)의 검색결과를 저장하기 위한 필드 - 검색행 1개
// => 객체를 저장하기 위한 필드 : 포함관계
// => 포함관계가 성립되기 위해서는 반드시 필드에 객체 저장
private MyComment1 comment;
//MYUSER 테이블(회원정보)의 검색결과를 저장하기 위한 필드 - 검색행 1개
private MyUser user;
public MyCommentUser2() {
// TODO Auto-generated constructor stub
}
public MyComment1 getComment() {
return comment;
}
public void setComment(MyComment1 comment) {
this.comment = comment;
}
public MyUser getUser() {
return user;
}
public void setUser(MyUser user) {
this.user = user;
}
}
cache : SELECT 명령의 검색결과를 임시 메모리(Cache Memory)에 저장하여 빠른 검색결과를 제공하기 위한 엘리먼트 (가독성 증가)
selectKey : SELECT 명령의 검색 결과값을 insert 엘리먼트의 parameterType 속성값으로 설정된 클래스의 필드값으로 저장하기 위한 엘리먼트
<selectKey resultType="int" keyProperty="commentNo" order="BEFORE">
- 검색행의 컬럼명과 resultType 속성값으로 설정된 클래스의 필드명이 같도록 작성
- resultType 속성을 사용하여 자동 매핑 기능으로 Java 객체 제공
- 검색행의 컬럼명과 resultType 속성값으로 설정된 클래스의 필드명이 모두 다른 경우 resultType 속성값으로 설정된 클래스의 객체 대신 NULL 제공
<idArg column="comment_no" javaType="_int"/>
<arg column="comment_id" javaType="string"/>
- 1:1 관계의 join 검색 결과를 저장
- resultMap 엘리먼트의 type 속성값으로 설정된 클래스의 필드가 Java 객체를 저장하기 위한 필드로 선언된 경우 하위 엘리먼트로 association 엘리먼트를 사용하여 Java 객체를 제공받아 필드에 저장되도록 설정
<association property="comment" javaType="MyComment1">
<id column="comment_no" property="commentNo"/>
<?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">
<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>
</mapper>
package xyz.itwill.mapper;
import java.util.List;
import xyz.itwill.dto.MyComment1;
import xyz.itwill.dto.MyComment2;
import xyz.itwill.dto.MyComment3;
import xyz.itwill.dto.MyCommentUser1;
import xyz.itwill.dto.MyCommentUser2;
public interface MyCommentMapper {
int insertComment1(MyComment1 comment);
int insertComment2(MyComment1 comment);
List<MyComment1> selectCommentList1();
List<MyComment2> selectCommentList2();
List<MyComment3> selectCommentList3();
List<MyCommentUser1> selectCommentUserList1();
List<MyCommentUser2> selectCommentUserList2();
}
package xyz.itwill.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import xyz.itwill.dto.MyComment1;
import xyz.itwill.dto.MyComment2;
import xyz.itwill.dto.MyComment3;
import xyz.itwill.dto.MyCommentUser1;
import xyz.itwill.dto.MyCommentUser2;
import xyz.itwill.mapper.MyCommentMapper;
public class MyCommentDAO extends AbstractSession {
private static MyCommentDAO _dao;
private MyCommentDAO() {
// TODO Auto-generated constructor stub
}
static {
_dao=new MyCommentDAO();
}
public static MyCommentDAO getDAO() {
return _dao;
}
public int insertComment1(MyComment1 comment) {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).insertComment1(comment);
} finally {
sqlSession.close();
}
}
public int insertComment2(MyComment1 comment) {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).insertComment2(comment);
} finally {
sqlSession.close();
}
}
public List<MyComment1> selectCommentList1() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectCommentList1();
} finally {
sqlSession.close();
}
}
public List<MyComment2> selectCommentList2() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectCommentList2();
} finally {
sqlSession.close();
}
}
public List<MyComment3> selectCommentList3() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectCommentList3();
} finally {
sqlSession.close();
}
}
public List<MyCommentUser1> selectCommentUserList1() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectCommentUserList1();
} finally {
sqlSession.close();
}
}
public List<MyCommentUser2> selectCommentUserList2() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectCommentUserList2();
} finally {
sqlSession.close();
}
}
}
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyComment1"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
MyComment1 comment1=new MyComment1();
comment1.setCommentId("abc");
comment1.setCommentContent("첫번째 게시글입니다.");
MyCommentDAO.getDAO().insertComment1(comment1);
MyComment1 comment2=new MyComment1();
comment2.setCommentId("xyz");
comment2.setCommentContent("두번째 게시글입니다.");
MyCommentDAO.getDAO().insertComment1(comment2);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
</head>
<body>
<h1>게시글 등록</h1>
<hr>
<h3>게시글이 성공적으로 삽입 되었습니다.</h3>
</body>
</html>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyComment1"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
MyComment1 comment3=new MyComment1();
comment3.setCommentId("opq");
comment3.setCommentContent("세번째 게시글입니다.");
MyCommentDAO.getDAO().insertComment2(comment3);
MyComment1 comment4=new MyComment1();
comment4.setCommentId("abc");
comment4.setCommentContent("네번째 게시글입니다.");
MyCommentDAO.getDAO().insertComment2(comment4);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
</head>
<body>
<h1>게시글 등록</h1>
<hr>
<h3>게시글이 성공적으로 삽입 되었습니다.</h3>
</body>
</html>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyComment1"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyComment1> commentList=MyCommentDAO.getDAO().selectCommentList1();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
</style>
</head>
<body>
<h1>게시글 목록</h1>
<hr>
<table>
<tr>
<td class="no">게시글번호</td>
<td class="name">게시글작성자</td>
<td class="content">게시글내용</td>
<td class="date">게시글작성일</td>
</tr>
<% for(MyComment1 comment:commentList) { %>
<tr>
<td><%=comment.getCommentNo() %></td>
<td><%=comment.getCommentId() %></td>
<td><%=comment.getCommentContent() %></td>
<td><%=comment.getCommentDate() %></td>
</tr>
<% } %>
</table>
</body>
</html>
<%@page import="xyz.itwill.dto.MyComment2"%>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyComment1"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyComment2> commentList=MyCommentDAO.getDAO().selectCommentList2();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
</style>
</head>
<body>
<h1>게시글 목록</h1>
<hr>
<table>
<tr>
<td class="no">게시글번호</td>
<td class="name">게시글작성자</td>
<td class="content">게시글내용</td>
<td class="date">게시글작성일</td>
</tr>
<% for(MyComment2 comment:commentList) { %>
<tr>
<td><%=comment.getNo() %></td>
<td><%=comment.getId() %></td>
<td><%=comment.getContent() %></td>
<td><%=comment.getDate() %></td>
</tr>
<% } %>
</table>
</body>
</html>
<%@page import="xyz.itwill.dto.MyComment3"%>
<%@page import="xyz.itwill.dto.MyComment2"%>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyComment1"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyComment3> commentList=MyCommentDAO.getDAO().selectCommentList3();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
</style>
</head>
<body>
<h1>게시글 목록</h1>
<hr>
<table>
<tr>
<td class="no">게시글번호</td>
<td class="name">게시글작성자</td>
<td class="content">게시글내용</td>
<td class="date">게시글작성일</td>
</tr>
<% for(MyComment3 comment:commentList) { %>
<tr>
<td><%=comment.getNo() %></td>
<td><%=comment.getName() %>(<%=comment.getId() %>)</td>
<td><%=comment.getContent() %></td>
<td><%=comment.getDate() %></td>
</tr>
<% } %>
</table>
</body>
</html>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyCommentUser1"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyCommentUser1> commentUserList=MyCommentDAO.getDAO().selectCommentUserList1();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
</style>
</head>
<body>
<h1>게시글 목록</h1>
<hr>
<table>
<tr>
<td class="no">게시글번호</td>
<td class="name">게시글작성자</td>
<td class="content">게시글내용</td>
<td class="date">게시글작성일</td>
</tr>
<% for(MyCommentUser1 commentUser:commentUserList) { %>
<tr>
<td><%=commentUser.getCommentNo() %></td>
<%-- <td><%=commentUser.getUserName() %>(<%=commentUser.getCommentId() %>)</td> --%>
<td><%=commentUser.getUserName() %>(<%=commentUser.getUserId() %>)</td>
<td><%=commentUser.getCommentContent() %></td>
<td><%=commentUser.getCommentDate() %></td>
</tr>
<% } %>
</table>
</body>
</html>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyCommentUser2"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyCommentUser2> commentUserList=MyCommentDAO.getDAO().selectCommentUserList2();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
</style>
</head>
<body>
<h1>게시글 목록</h1>
<hr>
<table>
<tr>
<td class="no">게시글번호</td>
<td class="name">게시글작성자</td>
<td class="content">게시글내용</td>
<td class="date">게시글작성일</td>
</tr>
<% for(MyCommentUser2 commentUser:commentUserList) { %>
<tr>
<td><%=commentUser.getComment().getCommentNo() %></td>
<%-- <td><%=commentUser.getUser().getUserName() %>(<%=commentUser.getComment().getCommentId() %>)</td> --%>
<td><%=commentUser.getUser().getUserName() %>(<%=commentUser.getUser().getUserId() %>)</td>
<td><%=commentUser.getComment().getCommentContent() %></td>
<td><%=commentUser.getComment().getCommentDate() %></td>
</tr>
<% } %>
</table>
</body>
</html>
create table myreply(reply_no number primary key, reply_id varchar2(50)
,reply_content varchar2(100),reply_date date,reply_comment_no number);
create sequence myreply_seq;
이름 널? 유형
---------------- -------- -------------
REPLY_NO NOT NULL NUMBER - 댓글 번호
REPLY_ID VARCHAR2(50) - 댓글 작성자(아이디)
REPLY_CONTENT VARCHAR2(100) - 댓글 내용
REPLY_DATE DATE - 댓글 작성일
REPLY_COMMENT_NO NUMBER - 게시글 번호
package xyz.itwill.dto;
public class MyReply {
private int replyNo;
private String replyId;
private String replyContent;
private String replyDate;
private int replyCommentNo;
public MyReply() {
// TODO Auto-generated constructor stub
}
public int getReplyNo() {
return replyNo;
}
public void setReplyNo(int replyNo) {
this.replyNo = replyNo;
}
public String getReplyId() {
return replyId;
}
public void setReplyId(String replyId) {
this.replyId = replyId;
}
public String getReplyContent() {
return replyContent;
}
public void setReplyContent(String replyContent) {
this.replyContent = replyContent;
}
public String getReplyDate() {
return replyDate;
}
public void setReplyDate(String replyDate) {
this.replyDate = replyDate;
}
public int getReplyCommentNo() {
return replyCommentNo;
}
public void setReplyCommentNo(int replyCommentNo) {
this.replyCommentNo = replyCommentNo;
}
}
- MYREPLY 테이블에 저장된 모든 댓글 검색
- MYREPLY 테이블에 저장된 모든 댓글중에서 가장 최근에 작성된 5개의 댓글만 검색
select rownum, reply.* from (select * from myreply order by reply_no desc) reply where rownum <= 5
- join을 사용한 select 문
resultMap 엘리먼트의 type 속성값으로 설정된 클래스의 필드가 Java 객체를 저장하기 위한 필드로 선언된 경우 하위 엘리먼트로 association 엘리먼트를 사용하여 Java 객체를 제공받아 필드에 저장되도록 설정
- 테이블 조인을 사용하지 않고 resultMap 엘리먼트의 매핑정보를 제공받아 2개 이상의 테이블의 컬럼값을 검색하여 Java 객체로 제공 가능
resultMap 엘리먼트의 하위 엘리먼트인 association 엘리먼트의 reultMap, select 속성
<association property="reply" resultMap="myReplyResultMap"/>
select 속성 : select 엘리먼트의 식별자를 속성값으로 설정
column 속성 : SELECT 명령으로 검색된 행의 컬럼명을 속성값으로 설정
association 엘리먼트에서만 사용하기 위한 SELECT 명령 등록
select문에서 검색된 행의 컬럼값과 매핑된 클래스(MyReplyUser)의 필드로 reply와 user가 저장됨
<?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>
package xyz.itwill.mapper;
import java.util.List;
import xyz.itwill.dto.MyReply;
import xyz.itwill.dto.MyReplyUser;
public interface MyReplyMapper {
int insertReply(MyReply reply);
List<MyReply> selectReplyList();
List<MyReply> selectCountReplyList();
List<MyReplyUser> selectReplyUserList1();
List<MyReplyUser> selectReplyUserList2();
}
package xyz.itwill.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import xyz.itwill.dto.MyReply;
import xyz.itwill.dto.MyReplyUser;
import xyz.itwill.mapper.MyReplyMapper;
public class MyReplyDAO extends AbstractSession {
private static MyReplyDAO _dao;
private MyReplyDAO() {
// TODO Auto-generated constructor stub
}
static {
_dao=new MyReplyDAO();
}
public static MyReplyDAO getDAO() {
return _dao;
}
public int insertReply(MyReply reply) {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyReplyMapper.class).insertReply(reply);
} finally {
sqlSession.close();
}
}
public List<MyReply> selectReplyList() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyReplyMapper.class).selectReplyList();
} finally {
sqlSession.close();
}
}
public List<MyReply> selectCountReplyList() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyReplyMapper.class).selectCountReplyList();
} finally {
sqlSession.close();
}
}
public List<MyReplyUser> selectReplyUserList1() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyReplyMapper.class).selectReplyUserList1();
} finally {
sqlSession.close();
}
}
public List<MyReplyUser> selectReplyUserList2() {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyReplyMapper.class).selectReplyUserList2();
} finally {
sqlSession.close();
}
}
}
<%@page import="xyz.itwill.dao.MyReplyDAO"%>
<%@page import="xyz.itwill.dto.MyReply"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//첫번째 게시글에 대한 댓글 삽입 - 3개
MyReply reply1=new MyReply();
reply1.setReplyCommentNo(1);
reply1.setReplyId("xyz");
reply1.setReplyContent("첫번째 게시글에 대한 댓글-1");
MyReplyDAO.getDAO().insertReply(reply1);
MyReply reply2=new MyReply();
reply2.setReplyCommentNo(1);
reply2.setReplyId("opq");
reply2.setReplyContent("첫번째 게시글에 대한 댓글-2");
MyReplyDAO.getDAO().insertReply(reply2);
MyReply reply3=new MyReply();
reply3.setReplyCommentNo(1);
reply3.setReplyId("xyz");
reply3.setReplyContent("첫번째 게시글에 대한 댓글-3");
MyReplyDAO.getDAO().insertReply(reply3);
//두번째 게시글에 대한 댓글 삽입 - 0개
//세번째 게시글에 대한 댓글 삽입 - 1개
MyReply reply4=new MyReply();
reply4.setReplyCommentNo(3);
reply4.setReplyId("abc");
reply4.setReplyContent("세번째 게시글에 대한 댓글-1");
MyReplyDAO.getDAO().insertReply(reply4);
//네번째 게시글에 대한 댓글 삽입 - 2개
MyReply reply5=new MyReply();
reply5.setReplyCommentNo(4);
reply5.setReplyId("xyz");
reply5.setReplyContent("네번째 게시글에 대한 댓글-1");
MyReplyDAO.getDAO().insertReply(reply5);
MyReply reply6=new MyReply();
reply6.setReplyCommentNo(4);
reply6.setReplyId("opq");
reply6.setReplyContent("네번째 게시글에 대한 댓글-2");
MyReplyDAO.getDAO().insertReply(reply6);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
</head>
<body>
<h1>댓글등록</h1>
<hr>
<h3>댓글이 성공적으로 삽입 되었습니다.</h3>
</body>
</html>
<%@page import="xyz.itwill.dao.MyReplyDAO"%>
<%@page import="xyz.itwill.dto.MyReply"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyReply> replyList=MyReplyDAO.getDAO().selectReplyList();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
.comment { width: 100px; }
</style>
</head>
<body>
<h1>댓글목록</h1>
<hr>
<table>
<tr>
<td class="no">댓글번호</td>
<td class="name">댓글작성자</td>
<td class="content">댓글내용</td>
<td class="date">댓글작성일</td>
<td class="comment">게시글번호</td>
</tr>
<% for(MyReply reply:replyList) { %>
<tr>
<td><%=reply.getReplyNo() %></td>
<td><%=reply.getReplyId() %></td>
<td><%=reply.getReplyContent() %></td>
<td><%=reply.getReplyDate() %></td>
<td><%=reply.getReplyCommentNo() %></td>
</tr>
<% } %>
</table>
</body>
</html>
<%@page import="xyz.itwill.dao.MyReplyDAO"%>
<%@page import="xyz.itwill.dto.MyReply"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyReply> replyList=MyReplyDAO.getDAO().selectCountReplyList();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
.comment { width: 100px; }
</style>
</head>
<body>
<h1>댓글목록</h1>
<hr>
<table>
<tr>
<td class="no">댓글번호</td>
<td class="name">댓글작성자</td>
<td class="content">댓글내용</td>
<td class="date">댓글작성일</td>
<td class="comment">게시글번호</td>
</tr>
<% for(MyReply reply:replyList) { %>
<tr>
<td><%=reply.getReplyNo() %></td>
<td><%=reply.getReplyId() %></td>
<td><%=reply.getReplyContent() %></td>
<td><%=reply.getReplyDate() %></td>
<td><%=reply.getReplyCommentNo() %></td>
</tr>
<% } %>
</table>
</body>
</html>
<%@page import="xyz.itwill.dao.MyReplyDAO"%>
<%@page import="xyz.itwill.dto.MyReplyUser"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyReplyUser> replyUserList=MyReplyDAO.getDAO().selectReplyUserList1();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
.comment { width: 100px; }
</style>
</head>
<body>
<h1>댓글목록</h1>
<hr>
<table>
<tr>
<td class="no">댓글번호</td>
<td class="name">댓글작성자</td>
<td class="content">댓글내용</td>
<td class="date">댓글작성일</td>
<td class="comment">게시글번호</td>
</tr>
<% for(MyReplyUser replyUser:replyUserList) { %>
<tr>
<td><%=replyUser.getReply().getReplyNo() %></td>
<%-- <td><%=replyUser.getUser().getUserName() %>(<%=replyUser.getReply().getReplyId() %>)</td> --%>
<td><%=replyUser.getUser().getUserName() %>(<%=replyUser.getUser().getUserId()%>)</td>
<td><%=replyUser.getReply().getReplyContent() %></td>
<td><%=replyUser.getReply().getReplyDate() %></td>
<td><%=replyUser.getReply().getReplyCommentNo() %></td>
</tr>
<% } %>
</table>
</body>
</html>
<%@page import="xyz.itwill.dao.MyReplyDAO"%>
<%@page import="xyz.itwill.dto.MyReplyUser"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyReplyUser> replyUserList=MyReplyDAO.getDAO().selectReplyUserList2();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
.comment { width: 100px; }
</style>
</head>
<body>
<h1>댓글목록</h1>
<hr>
<table>
<tr>
<td class="no">댓글번호</td>
<td class="name">댓글작성자</td>
<td class="content">댓글내용</td>
<td class="date">댓글작성일</td>
<td class="comment">게시글번호</td>
</tr>
<% for(MyReplyUser replyUser:replyUserList) { %>
<tr>
<td><%=replyUser.getReply().getReplyNo() %></td>
<%-- <td><%=replyUser.getUser().getUserName() %>(<%=replyUser.getReply().getReplyId() %>)</td> --%>
<td><%=replyUser.getUser().getUserName() %>(<%=replyUser.getUser().getUserId()%>)</td>
<td><%=replyUser.getReply().getReplyContent() %></td>
<td><%=replyUser.getReply().getReplyDate() %></td>
<td><%=replyUser.getReply().getReplyCommentNo() %></td>
</tr>
<% } %>
</table>
</body>
</html>
MYCOMMENT 테이블과 MYREPLY 테이블의 검색결과를 저장하기 위한 클래스
package xyz.itwill.dto;
import java.util.List;
public class MyCommentReply {
private int commentNo;
//MYCOMMENT 테이블(게시글정보)의 검색결과를 저장하기 위한 필드 - 검색행 : 1개
private MyComment1 comment;
//MYREPLY 테이블(댓글정보)의 검색결과를 저장하기 위한 필드 - 검색행 : 0개 이상
private List<MyReply> replyList;
public MyCommentReply() {
// TODO Auto-generated constructor stub
}
public int getCommentNo() {
return commentNo;
}
public void setCommentNo(int commentNo) {
this.commentNo = commentNo;
}
public MyComment1 getComment() {
return comment;
}
public void setComment(MyComment1 comment) {
this.comment = comment;
}
public List<MyReply> getReplyList() {
return replyList;
}
public void setReplyList(List<MyReply> replyList) {
this.replyList = replyList;
}
}
MYCOMMENT 테이블과 MYUSER 테이블 및 MYREPLY 테이블과 MYUSER 테이블의 검색결과를 저장하기 위한 클래스
MYCOMMENT 테이블(게시글정보)의 검색결과를 저장하기 위한 필드 (검색행 : 1개)
MYUSER 테이블(회원정보 - 게시글)의 검색결과를 저장하기 위한 필드 (검색행 : 1개)
MYREPLY 테이블(댓글정보)과 MYUSER 테이블(회원정보 - 댓글)의 검색결과를 저장하기 위한 필드 (검색행 : 0개 이상)
package xyz.itwill.dto;
import java.util.List;
public class MyCommentReplyUser {
//MYCOMMENT 테이블(게시글정보)의 검색결과를 저장하기 위한 필드 - 검색행 : 1개
private int commentNo;
private String commentId;
private String commentContent;
private String commentDate;
//MYUSER 테이블(회원정보 - 게시글)의 검색결과를 저장하기 위한 필드 - 검색행 : 1개
private MyUser user;
//MYREPLY 테이블(댓글정보)과 MYUSER 테이블(회원정보 - 댓글)의 검색결과를 저장하기 위한 필드 - 검색행 : 0개 이상
private List<MyReplyUser> replyUserList;
public MyCommentReplyUser() {
// TODO Auto-generated constructor stub
}
public int getCommentNo() {
return commentNo;
}
public void setCommentNo(int commentNo) {
this.commentNo = commentNo;
}
public String getCommentId() {
return commentId;
}
public void setCommentId(String commentId) {
this.commentId = commentId;
}
public String getCommentContent() {
return commentContent;
}
public void setCommentContent(String commentContent) {
this.commentContent = commentContent;
}
public String getCommentDate() {
return commentDate;
}
public void setCommentDate(String commentDate) {
this.commentDate = commentDate;
}
public MyUser getUser() {
return user;
}
public void setUser(MyUser user) {
this.user = user;
}
public List<MyReplyUser> getReplyUserList() {
return replyUserList;
}
public void setReplyUserList(List<MyReplyUser> replyUserList) {
this.replyUserList = replyUserList;
}
}
- 메소드 두개(MyComment1, MyReply)를 작성하여 검색
- 게시글번호를 전달받아 MYCOMMNET 테이블에 저장된 해당 게시글번호의 게시글을 검색하여 MyComment1 객체로 제공하는 엘리먼트 (검색행 : 1개)
- 게시글번호를 전달받아 MYREPLY 테이블에 저장된 해당 게시글번호의 댓글을 검색하여 MuReply 객체로 제공하는 엘리먼트 (검색행 0개 이상)
- 메소드 한개(MyCommentReply)를 작성하여 검색 (1:N join)
- 1:N 관계의 조인은 반드시 OUTER JOIN 사용하여 검색
- 댓글이 없는 게시글을 검색하기 위해 LEFT OUTER JOIN 사용
resultMap 엘리먼트의 type 속성값으로 설정된 클래스의 필드 자료형이 List인 경우 collection 엘리먼트를 사용하여 List 객체를 생성하여 필드에 저장되도록 설정
<collection property="replyList" ofType="MyReply">
- 클래스(selectCommentReplyUser)의 필드로 값을 저장할 수 있는 MYCOMMENT 테이블의 필드, 객체를 저장할 수 있는 MYUSER 클래스, List객체인 MyReplyUser 저장(검색행: 0개 이상)
- mycomment, myreply, myuser table join하여 검색
- mycomment join myuser on comment_id=user_id (게시글과 작성자 join)
- myreply join myuser on reply_id=user_id (댓글과 작성자 join)
- mycomment join myreply on comment_no=reply_comment_no (게시글과 댓글 join)
<?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">
<!-- 게시글번호를 전달받아 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>
package xyz.itwill.mapper;
public interface MyCommentMapper {
MyComment1 selectComment(int commentNo);
List<MyReply> selectCommentNoReplyList(int replyCommentNo);
MyCommentReply selectCommentReply(int commentNo);
MyCommentReplyUser selectCommentReplyUser(int commentNo);
}
selectComment() : 전달받은 게시글번호에 대한 게시글(1개)을 검색하여 반환
selectCommentNoReplyList() : 전달받은 게시글번호에 대한 댓글(0개 이상)을 검색하여 반환
selectCommentReply() : MyComment1과 MyReply table을 join 하여 댓글목록 검색
selectCommentReplyUser() : MyComment1, MyReply, MyUser table을 join 하여 댓글목록 검색
package xyz.itwill.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import xyz.itwill.dto.MyComment1;
import xyz.itwill.dto.MyComment2;
import xyz.itwill.dto.MyComment3;
import xyz.itwill.dto.MyCommentReply;
import xyz.itwill.dto.MyCommentReplyUser;
import xyz.itwill.dto.MyCommentUser1;
import xyz.itwill.dto.MyCommentUser2;
import xyz.itwill.dto.MyReply;
import xyz.itwill.mapper.MyCommentMapper;
public class MyCommentDAO extends AbstractSession {
private static MyCommentDAO _dao;
private MyCommentDAO() {
// TODO Auto-generated constructor stub
}
static {
_dao=new MyCommentDAO();
}
public static MyCommentDAO getDAO() {
return _dao;
}
public MyComment1 selectComment(int commentNo) {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectComment(commentNo);
} finally {
sqlSession.close();
}
}
public List<MyReply> selectCommentNoReplyList(int replyCommentNo) {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectCommentNoReplyList(replyCommentNo);
} finally {
sqlSession.close();
}
}
public MyCommentReply selectCommentReply(int commentNo) {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectCommentReply(commentNo);
} finally {
sqlSession.close();
}
}
public MyCommentReplyUser selectCommentReplyUser(int commentNo) {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).selectCommentReplyUser(commentNo);
} finally {
sqlSession.close();
}
}
}
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyCommentUser2"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
List<MyCommentUser2> commentUserList=MyCommentDAO.getDAO().selectCommentUserList2();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
</style>
</head>
<body>
<h1>게시글 목록</h1>
<hr>
<table>
<tr>
<td class="no">게시글번호</td>
<td class="name">게시글작성자</td>
<td class="content">게시글내용</td>
<td class="date">게시글작성일</td>
</tr>
<% for(MyCommentUser2 commentUser:commentUserList) { %>
<tr>
<td><%=commentUser.getComment().getCommentNo() %></td>
<%-- <td><%=commentUser.getUser().getUserName() %>(<%=commentUser.getComment().getCommentId() %>)</td> --%>
<td><%=commentUser.getUser().getUserName() %>(<%=commentUser.getUser().getUserId() %>)</td>
<%-- <td><%=commentUser.getComment().getCommentContent() %></td> --%>
<td>
<%-- <a href="commentReplySelect1.jsp?commentNo=<%=commentUser.getComment().getCommentNo()%>"> --%>
<a href="commentReplySelect2.jsp?commentNo=<%=commentUser.getComment().getCommentNo()%>">
<%=commentUser.getComment().getCommentContent() %>
</a>
</td>
<td><%=commentUser.getComment().getCommentDate() %></td>
</tr>
<% } %>
</table>
</body>
</html>
게시글 내용을 클릭 할 경우 전달값(게시글번호)을 반환받아 저장
int commentNo=Integer.parseInt(request.getParameter("commentNo"));
전달받은 게시글번호에 대한 게시글(1개)을 검색하여 반환하는 DAO 클래스의 메소드 호출
MyComment1 comment=MyCommentDAO.getDAO().selectComment(commentNo);
전달받은 게시글번호에 대한 댓글(0개 이상)을 검색하여 반환하는 DAO 클래스의 메소드 호출
List<MyReply> replyList=MyCommentDAO.getDAO().selectCommentNoReplyList(commentNo);
<%@page import="xyz.itwill.dto.MyReply"%>
<%@page import="java.util.List"%>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyComment1"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
if(request.getParameter("commentNo")==null) {
response.sendRedirect("commentUserListSelect2.jsp");
return;
}
//전달값(게시글번호)을 반환받아 저장
int commentNo=Integer.parseInt(request.getParameter("commentNo"));
//전달받은 게시글번호에 대한 게시글(1개)을 검색하여 반환하는 DAO 클래스의 메소드 호출
MyComment1 comment=MyCommentDAO.getDAO().selectComment(commentNo);
//전달받은 게시글번호에 대한 댓글(0개 이상)을 검색하여 반환하는 DAO 클래스의 메소드 호출
List<MyReply> replyList=MyCommentDAO.getDAO().selectCommentNoReplyList(commentNo);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
.comment { width: 100px; }
</style>
</head>
<body>
<h1>게시글과 댓글목록</h1>
<hr>
<%-- 게시글 출력 --%>
<table>
<tr>
<td width="200">게시글번호</td>
<td width="300"><%=comment.getCommentNo() %></td>
</tr>
<tr>
<td width="200">게시글작성자</td>
<td width="300"><%=comment.getCommentId() %></td>
</tr>
<tr>
<td width="200">게시글내용</td>
<td width="300"><%=comment.getCommentContent() %></td>
</tr>
<tr>
<td width="200">게시글작성일</td>
<td width="300"><%=comment.getCommentDate() %></td>
</tr>
</table>
<br>
<%-- 댓글목록 출력 --%>
<table>
<tr>
<td class="no">댓글번호</td>
<td class="name">댓글작성자</td>
<td class="content">댓글내용</td>
<td class="date">댓글작성일</td>
<td class="comment">게시글번호</td>
</tr>
<% if(replyList.isEmpty()) { %>
<tr>
<td colspan="5">댓글이 존재하지 않습니다.</td>
</tr>
<% } else { %>
<% for(MyReply reply:replyList) { %>
<tr>
<td><%=reply.getReplyNo() %></td>
<td><%=reply.getReplyId() %></td>
<td><%=reply.getReplyContent() %></td>
<td><%=reply.getReplyDate() %></td>
<td><%=reply.getReplyCommentNo() %></td>
</tr>
<% } %>
<% } %>
</table>
</body>
</html>
전달값(게시글번호)을 반환받아 저장
전달받은 게시글번호에 대한 게시글과 댓글목록을 검색하여 반환하는 DAO 클래스의 메소드 호출
<%@page import="xyz.itwill.dto.MyCommentReply"%>
<%@page import="xyz.itwill.dto.MyReply"%>
<%@page import="java.util.List"%>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyComment1"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
if(request.getParameter("commentNo")==null) {
response.sendRedirect("commentUserListSelect2.jsp");
return;
}
//전달값(게시글번호)을 반환받아 저장
int commentNo=Integer.parseInt(request.getParameter("commentNo"));
//전달받은 게시글번호에 대한 게시글과 댓글목록을 검색하여 반환하는 DAO 클래스의 메소드 호출
MyCommentReply commentReply=MyCommentDAO.getDAO().selectCommentReply(commentNo);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
.comment { width: 100px; }
</style>
</head>
<body>
<h1>게시글과 댓글목록</h1>
<hr>
<%-- 게시글 출력 --%>
<table>
<tr>
<td width="200">게시글번호</td>
<td width="300"><%=commentReply.getComment().getCommentNo() %></td>
</tr>
<tr>
<td width="200">게시글작성자</td>
<td width="300"><%=commentReply.getComment().getCommentId() %></td>
</tr>
<tr>
<td width="200">게시글내용</td>
<td width="300"><%=commentReply.getComment().getCommentContent() %></td>
</tr>
<tr>
<td width="200">게시글작성일</td>
<td width="300"><%=commentReply.getComment().getCommentDate() %></td>
</tr>
</table>
<br>
<%-- 댓글목록 출력 --%>
<table>
<tr>
<td class="no">댓글번호</td>
<td class="name">댓글작성자</td>
<td class="content">댓글내용</td>
<td class="date">댓글작성일</td>
<td class="comment">게시글번호</td>
</tr>
<% if(commentReply.getReplyList().isEmpty()) { %>
<tr>
<td colspan="5">댓글이 존재하지 않습니다.</td>
</tr>
<% } else { %>
<% for(MyReply reply:commentReply.getReplyList()) { %>
<tr>
<td><%=reply.getReplyNo() %></td>
<td><%=reply.getReplyId() %></td>
<td><%=reply.getReplyContent() %></td>
<td><%=reply.getReplyDate() %></td>
<td><%=reply.getReplyCommentNo() %></td>
</tr>
<% } %>
<% } %>
</table>
</body>
</html>
전달값(게시글번호)을 반환받아 저장
전달받은 게시글번호에 대한 게시글과 댓글목록을 검색하여 반환하는 DAO 클래스의 메소드 호출
<%@page import="xyz.itwill.dto.MyReplyUser"%>
<%@page import="xyz.itwill.dto.MyCommentReplyUser"%>
<%@page import="xyz.itwill.dto.MyReply"%>
<%@page import="java.util.List"%>
<%@page import="xyz.itwill.dao.MyCommentDAO"%>
<%@page import="xyz.itwill.dto.MyComment1"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
if(request.getParameter("commentNo")==null) {
response.sendRedirect("commentUserListSelect2.jsp");
return;
}
//전달값(게시글번호)을 반환받아 저장
int commentNo=Integer.parseInt(request.getParameter("commentNo"));
//전달받은 게시글번호에 대한 게시글과 댓글목록을 검색하여 반환하는 DAO 클래스의 메소드 호출
MyCommentReplyUser commentReplyUser=MyCommentDAO.getDAO().selectCommentReplyUser(commentNo);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MYBATIS</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
td {
border: 1px solid black;
text-align: center;
padding: 3px;
}
.no { width: 100px; }
.name { width: 150px; }
.content { width: 250px; }
.date { width: 200px; }
.comment { width: 100px; }
</style>
</head>
<body>
<h1>게시글과 댓글목록</h1>
<hr>
<%-- 게시글 출력 --%>
<table>
<tr>
<td width="200">게시글번호</td>
<td width="300"><%=commentReplyUser.getCommentNo() %></td>
</tr>
<tr>
<td width="200">게시글작성자</td>
<td width="300"><%=commentReplyUser.getUser().getUserName()%>(<%=commentReplyUser.getUser().getUserId()%>) </td>
</tr>
<tr>
<td width="200">게시글내용</td>
<td width="300"><%=commentReplyUser.getCommentContent() %></td>
</tr>
<tr>
<td width="200">게시글작성일</td>
<td width="300"><%=commentReplyUser.getCommentDate() %></td>
</tr>
</table>
<br>
<%-- 댓글목록 출력 --%>
<table>
<tr>
<td class="no">댓글번호</td>
<td class="name">댓글작성자</td>
<td class="content">댓글내용</td>
<td class="date">댓글작성일</td>
<td class="comment">게시글번호</td>
</tr>
<% if(commentReplyUser.getReplyUserList().isEmpty()) { %>
<tr>
<td colspan="5">댓글이 존재하지 않습니다.</td>
</tr>
<% } else { %>
<% for(MyReplyUser replyUser:commentReplyUser.getReplyUserList()) { %>
<tr>
<td><%=replyUser.getReply().getReplyNo() %></td>
<td><%=replyUser.getUser().getUserName()%>(<%=replyUser.getUser().getUserId()%>) </td>
<td><%=replyUser.getReply().getReplyContent() %></td>
<td><%=replyUser.getReply().getReplyDate() %></td>
<td><%=replyUser.getReply().getReplyCommentNo() %></td>
</tr>
<% } %>
<% } %>
</table>
</body>
</html>