본문 바로가기

학원/복기

[MyBatis] 비교연산자가 엘리먼트로 인식되는 에러 해결

테이블, 시퀀스를 새로 생성해준다

 

MYREPLY 테이블 : 게시글에 대한 댓글을 저장하기 위한 테이블

MYREPLY_SEQ : MYREPLY 테이블의 REPLY_NO 컬럼값으로 저장될 자동 증가값을 제공하는 시퀀스

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  	- 게시글 번호

 

DTO 생성

 

[MyReply]

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;
	}
}

 

 

xml 매퍼 

 

[MyReplyMapper.xml]

<?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 reply_no, reply_id, reply_content, reply_date, reply_comment_no
			from myreply order by reply_no desc
	</select>
</mapper>

 

 

인터페이스 매퍼

 

[MyReplyMapper]

package xyz.itwill.mapper;

import java.util.List;

import xyz.itwill.dto.MyReply;

public interface MyReplyMapper {
	int insertReply(MyReply reply);
	List<MyReply> selectReplyList();
}

 

 

DAO 

 

[MyReplyDAO]

package xyz.itwill.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import xyz.itwill.dto.MyReply;
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();
		}
	}
}

 

jsp 파일을 만들어서 댓글을 삽입해주자 

 

[replyInsert.jsp]

<%@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>

[MYREPLY 테이블]

 

 

jsp 파일로 댓글목록을 확인해보자

 

[replyListSelect.jsp]

<%@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: 300px; }
.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>

 


xml 매퍼 파일에 SQL 명령을 추가로 등록해보자

 

MYREPLY 테이블에 저장된 댓글 중 가장 최근에 작성된 5개의 댓글만 검색하는 SQL 명령 등록을 등록해볼 것이다

 

[MyReplyMapper.xml]

<!-- 에러 발생 -->
<select id="selectCountReplyList" resultType="MyReply">
	select rownum, reply.* from (select reply_no, reply_id, reply_content, reply_date
		, reply_comment_no from myreply order by reply_no desc) reply where rownum <= 5
</select>

 

하지만 XML 기반의 매퍼 파일에서는 SQL 명령이 등록된 엘리먼트에서 비교 연산자 중 > 또는 < 연산자를 사용할 경우 엘리먼트를 표현하는 기호로 인식되어 에러가 발생한다는 문제점이 있다.

 

비교연산자가 엘리먼트를 표현하는 기호로 인식되어 발생되는 에러 해결하기

 

해결법1) > 또는 < 비교 연산자를 엔티티 레퍼런스(회피문자)로 표현하여 SQL 명령 작성하기

<select id="selectCountReplyList" resultType="MyReply">
	select rownum, reply.* from (select reply_no, reply_id, reply_content, reply_date
		, reply_comment_no from myreply order by reply_no desc) reply where rownum &lt;= 5
</select>

 

해결법2) CDATA 세션을 사용하여 SQL 명령 작성하기 

<select id="selectCountReplyList" resultType="MyReply">
	<![CDATA[
	select rownum, reply.* from (select reply_no, reply_id, reply_content, reply_date
		, reply_comment_no from myreply order by reply_no desc) reply where rownum <= 5
	]]>
</select>

 

 

이제 인터페이스 매퍼를 등록해주자

 

인터페이스 매퍼

public interface MyReplyMapper {
	//...
        //...
	List<MyReply> selectCountReplyList();
}

 

DAO

//...
//...
public List<MyReply> selectCountReplyList() {
	SqlSession sqlSession=getSqlSessionFactory().openSession(true);
	try {
		return sqlSession.getMapper(MyReplyMapper.class).selectCountReplyList();
	} finally {
		sqlSession.close();
	}
}

 

jsp로 댓글목록 확인 

 

[replyCountListSelect.jsp]

<%@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: 300px; }
.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>