카테고리 없음

MyBatis with Board Project

Soul-Learner 2014. 4. 3. 23:48

MyBatis 를 이용한 Struts 2 게시판


Configuration.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>

<properties resource="board/db.properties" />


<typeAliases>

<typeAlias type="board.BoardVO" alias="Board" />

</typeAliases>


<environments default="development">

<environment id="development">

<transactionManager type="JDBC" />

<dataSource type="POOLED">

<property name="driver" value="${driver}" />

<property name="url" value="${url}" />

<property name="username" value="${username}" />

<property name="password" value="${password}" />

</dataSource>

</environment>

</environments>

<mappers>

<mapper resource="board/BoardMapper.xml" />

</mappers>


</configuration>



struts.xml 에 선언된 액션의 이름은 PageUtilBean의  link 속성의 값(private String link = "boardList")과 일치해야한다.

<action name="boardList" class="board.BoardAction" method="boardList">

        <interceptor-ref name="params"/>

        <result>board/boardList.jsp</result>

</action>



BoardAction.java

public class BoardAction extends ActionSupport implements Preparable, ModelDriven<BoardVO> {

private BoardVO board;

private String resultMsg;                   //입력, 수정, 삭제시 결과 메시지 저장

private List<BoardVO> boardList;

private int num;                                //글번호

private int page = 1;                         //이용자가 요청한 페이지 번호,처음 실행시 오류를 방지하려면 반드시 1 로 초기화해야 함

private PageUtilBean pageBean;

......

 ...........(중략)

        /** 이용자가 리스트 요청시 실행되는 액션 메소드

        PageUtilBean의 인스턴스를 생성하고 Service 객체로 전달한다

        Service 객체의 getBoardList(page) 호출시 메소드 내부에서 PageUtilBean.init()호출하여 초기화 됨

        PageUtilBean이 초기화되면 뒤 이어 호출되는 JSP에서 Action 의 멤버변수인 pageBean을 사용함

        struts.xml 에 등록한 액션의 이름은 boardList 이므로 PageUtilBean을 이용할 경우 반드시 확인하여 일치하도록 설정해야 함

        */

public String boardList() throws Exception {

pageBean = new PageUtilBean();

BoardService service = new BoardService(pageBean);

boardList = service.getBoardList(page);

return SUCCESS;

}


        /** 이용자가 요청한 특정 페이지 번호는 params 인터셉터에 의해 현재 액션의 멤버 변수인 page 에 설정된다 */

public void setPage(int page) {

this.page = page;

}


        /** JSP 에서 ${pageBean.navStr}, ${pageBean.currPage}, ${pageBean.totalPages} 등을 사용할 수 있도록 getter 메소드 선언*/

public PageUtilBean getPageBean() {

return pageBean;

}


...........

  ........(생략)

}



BoardMapper.java

package board;


import java.util.*;


import org.apache.ibatis.annotations.Param;


public interface BoardMapper {

public List<BoardVO> boardList();

public List<BoardVO> boardListPg(@Param("pageNo")int page, @Param("rowsPerPage")int rowsPerPage);

public BoardVO getBoard(int num);

public int boardInsert(BoardVO board);

public int boardUpdate(BoardVO board);

public int boardDelete(int num);

}



BoardMapper.xml (아래의 선언에서 SELECT 문장은 Board(별칭)와 매핑되므로 SELECT 문장의 컬럼명과 Board 클래스의 속성명 일치해야 한다

<?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="board.BoardMapper">


<select id="boardList" resultType="Board">

   SELECT num, subject, writer, reg_date

   FROM board

   ORDER BY num DESC

</select>

<select id="boardListPg" resultType="Board">

   SELECT num, subject, writer, reg_date, pageNo, totalPages, totalCnt FROM

  (

  SELECT T1.*,

CEIL(ROWNUM/#{rowsPerPage}+1) AS pageNo,

CEIL(totalCnt/#{rowsPerPage}+1) AS totalPages FROM

(

SELECT num, subject, writer, reg_date, COUNT(*)OVER() AS totalCnt 

FROM board b ORDER BY num DESC

            ) T1

  )

  WHERE pageNo=#{pageNo}

</select>

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

SELECT num, subject, writer, reg_date, email, content

FROM board

WHERE num=#{num}

</select>

<insert id="boardInsert" parameterType="Board">

INSERT INTO board (num, subject, content, writer, passwd, reg_date, ref)

VALUES (BOARD_NUM.NEXTVAL, 

#{subject}, #{content},#{writer},#{passwd},sysdate,#{ref})

</insert>

<update id="boardUpdate" parameterType="Board">

UPDATE board SET subject=#{subject}, content=#{content}

WHERE num=#{num}

</update> 

<delete id="boardDelete">

DELETE FROM board WHERE num=#{num}

</delete>


</mapper>



BoardMybatisDAO.java

package board;


import java.io.*;

import java.util.*;


import org.apache.ibatis.io.*;

import org.apache.ibatis.session.*;


public class BoardMybatisDAO {

private static BoardMybatisDAO instance = new BoardMybatisDAO();


private String resource = "board/Configuration.xml"; //DB 연결정보, DB인터페이스, SQL문장, 모델클래스 정보

private Reader reader;

private SqlSessionFactory sqlMapper;

public static BoardMybatisDAO getInstance() {

return instance;

}

private BoardMybatisDAO() {

try {

reader = Resources.getResourceAsReader(resource);

sqlMapper = new SqlSessionFactoryBuilder().build(reader);

} catch (IOException e) {

e.printStackTrace();

}

}

public List<BoardVO> boardList() {

List<BoardVO> boardList = null;

SqlSession session = sqlMapper.openSession();

try {

BoardMapper mapper = session.getMapper(BoardMapper.class);

boardList = mapper.boardList();

//session.commit();

} finally {

session.close();

}

return boardList;

}


public List<BoardVO> boardList(int page, int rowsPerPage) {

List<BoardVO> boardList = null;

SqlSession session = sqlMapper.openSession();

try {

BoardMapper mapper = session.getMapper(BoardMapper.class); //DB인터페이스 객체생성

boardList = mapper.boardListPg(page, rowsPerPage);

//session.commit();

} finally {

session.close();

}

return boardList;

}

public BoardVO getBoard(int num) {

BoardVO board = null;

SqlSession session = sqlMapper.openSession();

try {

BoardMapper mapper = session.getMapper(BoardMapper.class);

board = mapper.getBoard(num);

//session.commit();

} finally {

session.close();

}

return board;

}

public boolean boardInsert(BoardVO board) {

SqlSession session = sqlMapper.openSession();

try {

BoardMapper mapper = session.getMapper(BoardMapper.class);

int rows = mapper.boardInsert(board);

if(rows>0) {

session.commit();

return true;

}

} finally {

session.close();

}

return false;

}

public boolean boardUpdate(BoardVO board) {

SqlSession session = sqlMapper.openSession();

try {

BoardMapper mapper = session.getMapper(BoardMapper.class);

int rows = mapper.boardUpdate(board);

if(rows>0) {

session.commit();

return true;

}

} finally {

session.close();

}

return false;

}

public boolean boardDelete(int num) {

SqlSession session = sqlMapper.openSession();

try {

BoardMapper mapper = session.getMapper(BoardMapper.class);

int rows = mapper.boardDelete(num);

if(rows>0) {

session.commit();

return true;

}

} finally {

session.close();

}

return false;

}

}



Pageable.java

package board;

/**

* 이 인터페이스는 데이터베이스 테이블의 한개의 레코드 정보를 저장할 클래스(VO)가 

* 구현할 경우 PageUtilBean에서 연결하여 페이지 하단에 페이지 네비게이션 링크를 생성

* 하는 기능을 사용할 수 있다. DAO 측에서는 SQL을 사용하여 총 레코드 수(ttcnt), 

* 총 페이지 수(ttpage), 현재 페이지 번호(page)를 VO에게 설정해야 주어야만 

* PageUtilBean에서 VO에 접근하여 해당 정보를 기반으로 페이지 네비게이션 링크를 생성할 수 있다

* DAO측에서 사용하는 SQL문장의 형태는 이 코드 아래에 있는 예문을 참고하기 바란다

*/

public interface Pageable {


/**현재 페이지 번호*/

public int getPageNo();

public void setPageNo(int pageNo);

/**총 레코드 수*/

public int getTotalCnt();

public void setTotalCnt(int totalCnt);

/**총 페이지 수*/

public int getTotalPages();

public void setTotalPages(int totalPages);

}

/*

 select rn, empno, ename, page, ttpage, ttcnt from

 (

  select T1.*, rownum rn,

FLOOR((rownum-1)/?+1) as page,

FLOOR((TTCNT-1)/?+1) as TTPAGE from

(

select e.*,COUNT(*)OVER() as TTCNT from emp e order by empno

    ) T1

 )

 where page=?

 

 ?:rowsPerPage

 ?:rowsPerPage

 ?:page

*/



BoardVO.java

package board;


import java.util.Date;



public class BoardVO implements Pageable {

private int num;

private String writer;

private String email;

private String subject;

private String passwd;

private Date reg_date;

private int ref;

private String content;

/* Fields for Pageable. MyBatis를 사용할 경우 아래의 변수명은 MyBatis의 SQL문장의 SELECT 절에서 사용되는 컬럼명과 일치해야 함 */

private int pageNo;

private int totalCnt;

private int totalPages;


public BoardVO(){

}

public BoardVO(int num, String writer, String email, String subject,

String passwd, Date reg_date, int ref, String content) {

super();

this.num = num;

this.writer = writer;

this.email = email;

this.subject = subject;

this.passwd = passwd;

this.reg_date = reg_date;

this.ref = ref;

this.content = content;

}

public int getNum() {

return num;

}

public void setNum(int num) {

this.num = num;

}

public String getWriter() {

return writer;

}

public void setWriter(String writer) {

this.writer = writer;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

public String getSubject() {

return subject;

}

public void setSubject(String subject) {

this.subject = subject;

}

public String getPasswd() {

return passwd;

}

public void setPasswd(String passwd) {

this.passwd = passwd;

}

public Date getReg_date() {

return reg_date;

}

public void setReg_date(Date reg_date) {

this.reg_date = reg_date;

}

public int getRef() {

return ref;

}

public void setRef(int ref) {

this.ref = ref;

}

public String getContent() {

return content;

}

public void setContent(String content) {

this.content = content;

}

@Override

public String toString() {

return "BoardVO [num=" + num + ", writer=" + writer + ", email="

+ email + ", subject=" + subject + ", passwd=" + passwd

+ ", reg_date=" + reg_date + ", ref=" + ref + ", content="

+ content + "]";

}


@Override

public int getPageNo() {

return pageNo;

}


@Override

public void setPageNo(int pageNo) {

this.pageNo = pageNo;

}


@Override

public int getTotalCnt() {

return totalCnt;

}


@Override

public void setTotalCnt(int totalCnt) {

this.totalCnt = totalCnt;

}


@Override

public int getTotalPages() {

return totalPages;

}


@Override

public void setTotalPages(int totalPages) {

this.totalPages = totalPages;

}

}



PageUtilBean 이 사용되는 경우의 BoardService.java 의 내용

package board;


import java.util.List;

import java.util.Map;


import com.opensymphony.xwork2.ActionContext;


public class BoardService {


private PageUtilBean pageBean;

public BoardService(){}

public BoardService(PageUtilBean pageBean){

this.pageBean = pageBean;

}

public boolean boardSave(BoardVO vo){


if(isLogon()){

Map<String,Object> map = ActionContext.getContext().getSession();

vo.setWriter((String)map.get("id"));

vo.setPasswd((String)map.get("pwd"));

/*

BoardDao dao = new BoardDao();

return dao.boardInsert(vo);*/

BoardMybatisDAO dao = BoardMybatisDAO.getInstance();

return dao.boardInsert(vo);

}

return false;

}


public List<BoardVO> getBoardList() {

/*BoardDao dao = new BoardDao();

return dao.boardList();*/

BoardMybatisDAO dao = BoardMybatisDAO.getInstance();

return dao.boardList();

}

public List<BoardVO> getBoardList(int page) {

BoardMybatisDAO dao = BoardMybatisDAO.getInstance();

int rowsPerPage = 3;

List<BoardVO> list = dao.boardList(page, rowsPerPage);

pageBean.init(page, list, rowsPerPage, 5); // page(액션에서 전달된 요청페이지 번호), list<Pageable>, rowsPerPage, numsPerPage

return list;

}

public BoardVO getBoard(int num){

/*BoardDao dao = new BoardDao();

return dao.boardDetail(num);*/

BoardMybatisDAO dao = BoardMybatisDAO.getInstance();

return dao.getBoard(num);

}


public boolean updateBoard(BoardVO board) {

/*BoardDao dao = new BoardDao();

return dao.boardUpdate(board);*/

BoardMybatisDAO dao = BoardMybatisDAO.getInstance();

return dao.boardUpdate(board);

}


public boolean deleteBoard(int num) {

/*BoardDao dao = new BoardDao();

return dao.boardDelete(num);*/

BoardMybatisDAO dao = BoardMybatisDAO.getInstance();

return dao.boardDelete(num);

}

public boolean isLogon() {

if(ActionContext.getContext().getSession().get("logon")==null) {

return false;

}

return true;

}

}



boardList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="EUC-KR"%>

<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html>

<html>

<head>

<title>게시판 리스트 </title>

<style type="text/css">

body {text-align: center; }

table { margin:0 auto;}

table caption {text-align: right; }

td{ border-bottom: dotted ;}

th{ background-color: gray;}

body{ text-align: center;}

a { text-decoration: none; }

#navTd { border:none; text-align: center; height:40px;}

#navBar {display:inline; text-align: center; height:40px;}

</style>

<script type="text/javascript">

function search(){

}

</script>

</head>

<body>

<h2>[ 게 시 판 ]</h2>

<table >

<caption>${pageBean.currPage} / ${pageBean.totalPages} </caption>

<tr><th width="70">글번호</th><th width="300">제목</th><th width="100">작성자</th><th width="100">작성일</th></tr>

<s:iterator value="boardList">

<tr>

<td><s:property value="num"/></td>

<td align="left">

<s:url id="readUrl" action="boardRead">

<s:param name="num"><s:property value="num"/></s:param>

</s:url>

<s:a href="%{readUrl}"><s:property value="subject"/></s:a>

</td>

<td><s:property value="writer"/></td>

<td><s:date name="reg_date" format="yyyy-MM-dd"/></td>

</tr>

</s:iterator>

<tr><td id="navTd" colspan="4">${pageBean.navStr}</td></tr>

</table>


<a href="boardInput"> <input type="button" value="글쓰기"> </a>


<s:form name="searchform" action="boardSearch">

<select name='sel'>

<option value="none">선택</option>

<option value="writer">작성자</option>

<option value="content">글 내용</option>

</select>

<input type="text" id="sitext"  name="sntext" > 

<input type="button" value="검색" onclick="search();">

</s:form>

</body>

</html>


struts2_board_pageBean_mybatis.zip