Jun's Blog

[Java] IBatis를 이용한 게시판 CRUD 예제 본문

High Java/IBatis

[Java] IBatis를 이용한 게시판 CRUD 예제

Fizzyelf 2020. 10. 26. 21:00

create table jdbc_board(
    board_no number not null,  -- 번호(자동증가)
    board_title varchar2(100) not null, -- 제목
    board_writer varchar2(50) not null, -- 작성자
    board_date date not null,   -- 작성날짜
    board_content clob,     -- 내용
    constraint pk_jdbc_board primary key (board_no)
);
create sequence board_seq
    start with 1   -- 시작번호
    increment by 1; -- 증가값

 


1) MainBoard

package kr.or.ddit.board;

import java.util.List;
import java.util.Scanner;

import kr.or.ddit.board.service.BoardServiceImpl;
import kr.or.ddit.board.service.IBoardService;
import kr.or.ddit.board.vo.BoardVO;

public class MainBoard {
	
	private IBoardService bService; 
	private Scanner sc;
	
	public MainBoard() {
		sc = new Scanner(System.in);
		bService = new BoardServiceImpl();
	}
	
	/**
	 * 메뉴를 출력하는 메서드
	 */
	public void displayMenu() {
		System.out.println();
		System.out.println("----------------------");
		System.out.println("  1. 전체 목록 출력");
		System.out.println("  2. 새글 작성");
		System.out.println("  3. 수정");
		System.out.println("  4. 삭제");
		System.out.println("  5. 검색");
		System.out.println("  6. 작업 끝.");
		System.out.println("----------------------");
		System.out.print("원하는 작업 선택 >> ");
	}
	
	
	
	
	/**
	 * 프로그램을 시작 메서드
	 */
	public void start() {
		int input;
		
		do {
			displayMenu();
			input = sc.nextInt();
			switch (input) {
			case 1 :
				DisplayBoardAll();	// 전체 목록 출력
				break;
			case 2 : 
				insertBoard();	// 새글 작성
				break;
			case 3 : 
				UpdateBoard();	// 수정
				break;
			case 4 : 
				DeleteBoard();	// 삭제
				break;
			case 5 :
				SearchBoard();	// 검색
				break;
			case 6 : 
				System.out.println("작업을 마칩니다.");
				break;
			default:
				System.out.println("번호를 잘못 입력하셨습니다. 다시 입력해주세요");
			}
		} while(input != 6);
	}
	
	/**
	 * 검색 메서드
	 */
	private void SearchBoard() {
		sc.nextLine();	// 입력 버퍼 지우기
		System.out.println();
		System.out.println("검색할 정보를 입력하세요.");
		
		
		System.out.print(" 제목  >> ");
		String boardTitle = sc.nextLine().trim();
		
		System.out.print(" 작성자 >> ");
		String boardWriter = sc.nextLine().trim();
		
		System.out.print(" 내용 >> ");
		String boardContent = sc.nextLine().trim();
		
		BoardVO bv = new BoardVO();
		bv.setBoardTitle(boardTitle);
		bv.setBoardWriter(boardWriter);
		bv.setBoardContent(boardContent);
		
		List<BoardVO> bList = bService.SearchBoard(bv);
		
		// 입력한 정보로 검색한 내용을 출력하기
		System.out.println();
		System.out.println("--------------------------------------");
		System.out.println("게시판\t번호\t제목\t\t작성자\t작성날짜\t\t\t\t내  용");
		System.out.println("--------------------------------------");
	
		
		for (BoardVO bVO : bList) {
			System.out.println("\t"+bVO.getBoardNo() + "\t"+  bVO.getBoardTitle() + "\t" + bVO.getBoardWriter() + "\t"
					+ bVO.getBoardDate() + "\t\t" + bVO.getBoardContent());
		}
		
		System.out.println("--------------------------------------");
		System.out.println("검색작업 끝...");
		
	}

	/**
	 * 게시글 삭제 메서드
	 */
	private void DeleteBoard() {
		System.out.println();
		System.out.println("삭제할 게시물 번호를 입력하세요.");
		System.out.print("게시물 번호 >> ");
		String boardNo = sc.next();
		
		int cnt = bService.DeleteBoard(boardNo);
		
		if(cnt > 0) {
			System.out.println(boardNo + "번 게시물 삭제 성공");
		} else {
			System.out.println(boardNo + "번 게시물 삭제 성공");
		}
	}

	/**
	 * 게시글 수정 메서드
	 */
	private void UpdateBoard() {
		boolean chk = false;	// 기존 회원 존재여부 체크 
		String boardNo = "";
		
		do {
			System.out.println();
			System.out.println("수정할 게시물 번호를 입력하세요.");
			System.out.print("게시물 번호 >> ");
			boardNo = sc.next();
			
			chk = getBoard(boardNo);
			
			if(!chk) {
				System.out.println(boardNo + "인 게시물은 없습니다.");
				System.out.println("다시 입력해주세요");
			}
		} while(chk== false);
		
		System.out.print("제목 >> ");
		String boardTitle = sc.next();
		
		sc.nextLine();
		System.out.print("내용 >> ");
		String boardContent = sc.nextLine();
		
		
		BoardVO bv = new BoardVO();
		
		bv.setBoardNo(boardNo);
		bv.setBoardTitle(boardTitle);
		bv.setBoardContent(boardContent);
		
		int cnt = bService.updateBoard(bv);
		
		if(cnt > 0) {
			System.out.println(boardNo + "번 글 수정 완료");
		} else {
			System.out.println(boardNo + "번 글 수정 실패");
		}
		
	}

	private boolean getBoard(String boardNo) {
		return bService.getBoard(boardNo);
	}

	/**
	 * 전체 출력 메서드
	 */
	private void DisplayBoardAll() {

		System.out.println();
		System.out.println("-----------------------------------------------------------------------");
		System.out.println("게시판\t번호\t제목\t\t작성자\t작성날짜\t\t\t\t내  용");
		System.out.println("-----------------------------------------------------------------------");

		List<BoardVO> bList = bService.DisplayBoardAll();

		for (BoardVO bVO : bList) {
			System.out.println("\t"+bVO.getBoardNo() + "\t"+  bVO.getBoardTitle() + "\t" + bVO.getBoardWriter() + "\t"
					+ bVO.getBoardDate() + "\t\t" + bVO.getBoardContent());
		}

		System.out.println("------------------------------------------");
		System.out.println("출력 작업 끝...");
	}


	/**
	 * 새글을 작성하는 메서드
	 */
	private void insertBoard() {

		 System.out.println();
	      System.out.println("게시판 작성을 위해 이름을 먼저 입력해주세요");
	      sc.nextLine();
	      System.out.print("작성자 이름 >> ");
	      String boardWriter = sc.nextLine();

	      System.out.print("제목 >> ");
	      String boardTitle = sc.nextLine();
	      
	      System.out.print("내용 >> ");
	      String boardContent = sc.nextLine();
	   
	      BoardVO bv = new BoardVO();
	      
	      bv.setBoardWriter(boardWriter);
	      bv.setBoardTitle(boardTitle);
	      bv.setBoardContent(boardContent);
	      
	      int cnt = bService.insertBoard(bv);
	      
	      if(cnt > 0) {
	         System.out.println(boardWriter + "님 작성 성공");
	      }else {
	         
	         System.out.println(boardWriter + "님 작성 실패");
	      }
	   }
	
	
	/**
	 * 메인
	 */
	public static void main(String[] args) {
	      MainBoard mb = new MainBoard();
	      mb.start();
	   }
}

 

2) IBoardService

package kr.or.ddit.board.service;

import java.util.List;

import kr.or.ddit.board.vo.BoardVO;

public interface IBoardService {

	public int insertBoard(BoardVO bv);

	public List<BoardVO> DisplayBoardAll();

	public int updateBoard(BoardVO bv);

	public boolean getBoard(String boardNo);

	public int DeleteBoard(String boardNo);

	public List<BoardVO> SearchBoard(BoardVO bv);

}

 

3) BoardServiceImpl

package kr.or.ddit.board.service;

import java.util.List;

import kr.or.ddit.board.dao.BoardDaoImpl;
import kr.or.ddit.board.dao.IBoardDao;
import kr.or.ddit.board.vo.BoardVO;

public class BoardServiceImpl implements IBoardService{

	private IBoardDao bDao;
	
	public BoardServiceImpl() {
		bDao = BoardDaoImpl.getInstance();
	}
	
	@Override
	public int insertBoard(BoardVO bv) {
		return bDao.insertBoard(bv);
	}
	
	@Override
	public List<BoardVO> DisplayBoardAll() {
		return bDao.DisplayBoardAll();
	}
	@Override
	public int updateBoard(BoardVO bv) {
		return bDao.updateBoard(bv);
	}
	@Override
	public boolean getBoard(String boardNo) {
		return bDao.getBoard(boardNo);
	}
	@Override
	public int DeleteBoard(String boardNo) {
		return bDao.DeleteBoard(boardNo);
	}
	@Override
	public List<BoardVO> SearchBoard(BoardVO bv) {
		return bDao.SearchBoard(bv);
	}	
}

 

4)  IBoardDao

package kr.or.ddit.board.dao;

import java.util.List;

import kr.or.ddit.board.vo.BoardVO;

public interface IBoardDao {

	public int insertBoard(BoardVO bv);

	public List<BoardVO> DisplayBoardAll();

	public int updateBoard(BoardVO bv);

	public boolean getBoard(String boardNo);

	public int DeleteBoard(String boardNo);

	public List<BoardVO> SearchBoard(BoardVO bv);

}

 

5) BoardDaoImpl

package kr.or.ddit.board.dao;

import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

import kr.or.ddit.board.vo.BoardVO;
import kr.or.ddit.util.JDBCUtil;
import kr.or.ddit.util.SqlMapClientFactory;

public class BoardDaoImpl implements IBoardDao {

	private static IBoardDao bDao;

	private SqlMapClient smc;
	
	private BoardDaoImpl() {
		smc = SqlMapClientFactory.getInstance();
	}
	
	public static IBoardDao getInstance() {
		if(bDao == null) {
			bDao = new BoardDaoImpl();
		}
		return bDao;
	}
	
	@Override
	public int insertBoard(BoardVO bv) {
		
		int cnt = 0;
		
		try {
			Object obj = smc.insert("boardTest.insertBoard", bv);
			
			if(obj == null) {
				cnt = 1;
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return cnt;
	}
	
	@Override
	public int DeleteBoard(String boardNo) {
		int cnt = 0;
		
		try {
			cnt = smc.delete("boardTest.deleteBoard", boardNo);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return cnt;
	}

	@Override
	public int updateBoard(BoardVO bv) {
		int cnt = 0;
		
		try {
			cnt = smc.update("boardTest.updateBoard", bv);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return cnt;
	}
	
	@Override
	public List<BoardVO> DisplayBoardAll() {
		List<BoardVO> bList = new ArrayList<>();

		try {
			bList = smc.queryForList("boardTest.getBoardAll");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return bList;
	}


	@Override
	public boolean getBoard(String boardNo) {
		boolean chk = false;

		try {
			int cnt = (int) smc.queryForObject("boardTest.getBoard", boardNo);
			
			if(cnt > 0) {
				chk = true;
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
	
		return chk;
	}


	@Override
	public List<BoardVO> SearchBoard(BoardVO bv) {
		List<BoardVO> bList = new ArrayList<>();

		try {
			bList = smc.queryForList("boardTest.SearchBoard", bv);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return bList;
	}
}

 

6) SqlMapClientFactory

package kr.or.ddit.util;

import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;

/**
 * SqlMapClient 객체를 제공하는 팩토리 클래스  
 */
public class SqlMapClientFactory {
	private static SqlMapClient smc;	// SqlMapClient 객체 변수 선언
	
	private SqlMapClientFactory() {
		
	}
	
	public static SqlMapClient getInstance() {
		if(smc == null) {
			try {
				
				// 1-1. xml 문서 읽어오기
				Charset charset = Charset.forName("UTF-8"); // 설정파일의 인코딩 설정
				Resources.setCharset(charset);
				Reader rd = Resources.getResourceAsReader("SqlMapConfig.xml");
				
				// 1-2. 위에서 읽어온 Reader 객체를 이용하여
				//      실제 작업을 진행할 객체 생성
				smc = SqlMapClientBuilder.buildSqlMapClient(rd);
				
				rd.close();
				
			} catch(IOException e) {
				System.err.println("SqlMapClient 객체 생성 실패!");
				e.printStackTrace();
			}
		}
		
		return smc;
		
	}
}

 

7) Board.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
			PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
			"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<!-- namespace속성 : 아래에서 작성한 SQL을 호출할 때 같이 사용된다. -->			
<sqlMap namespace="boardTest">
	<!-- 
		이 영역에 sql문에 맞는 태그를 사용하여 SQL문을 기술한다.
		
		사용할 수 있는 기본적인 태그들
		<select> ~~~ </select>
		<insert> ~~~ </insert>
		<update> ~~~ </update>
		<delete> ~~~ </delete>
	 
	 위 태그에서 사용되는 속성들
	 1) id 속성 : 해당 태그를 호출할 때 <SqlMap> 태그의 namespace와 연결하여 사용하는 이름
	 
	 2) parameterClass 속성 : sql문에 사용될 데이터가 들어있는 객체를 지정한다.
	 				 	     (보통은 VO클래스, 자바의 자료형 이름 등이 사용된다)
	 				 	     (typeAlias로 지정한 alias명을 사용할 수 있다.)
	 				 	     
	 3) resultClass 속성 : select 문을 실행한 결과를 닫을 객체를 지정한다.
	                     (보통 VO클래스나 자바의 자료형 이름을 사용한다.) 				 	     
	 
	 -->
	 

	<resultMap class="boardVO" id="boardMap">
	 	<result property="boardNo" column="board_no"/>
	 	<result property="boardWriter" column="board_writer"/>
	 	<result property="boardTitle" column="board_title"/>
	 	<result property="boardDate" column="board_date"/>
	 	<result property="boardContent" column="board_content"/>
	 </resultMap>

	<insert id="insertBoard" parameterClass="boardVO">
	INSERT INTO JDBC_BOARD 
    (BOARD_NO, BOARD_WRITER, BOARD_TITLE, BOARD_DATE, BOARD_CONTENT)
    VALUES (board_seq.nextval, #boardWriter#, #boardTitle#, sysdate, #boardContent#) 
	</insert>
	
	<delete id="deleteBoard" parameterClass="String">
	DELETE FROM JDBC_BOARD WHERE BOARD_NO = #boardNo# 
	</delete>

	<update id="updateBoard" parameterClass="boardVO">
	UPDATE JDBC_BOARD
	   SET BOARD_TITLE = #boardTitle# ,
	       BOARD_CONTENT = #boardContent# 
     WHERE BOARD_NO = #boardNo#
	</update>

	
	<select id="getBoardAll" resultMap="boardMap">
		select * from JDBC_BOARD
	</select>
	
	<select id="getBoard" resultClass="int">
		SELECT COUNT(*) CNT  
		  FROM JDBC_BOARD
		 WHERE BOARD_NO = #boardNo# 
	</select>

	<select id="SearchBoard" parameterClass="boardVO" resultMap="boardMap">
	 SELECT * FROM JDBC_BOARD WHERE 1=1
	 
	 	<isNotEmpty property="boardWriter">
	 		AND BOARD_WRITER = #boardWriter#
	 	</isNotEmpty>
	 	
	 	<isNotEmpty property="boardTitle">
	 		AND BOARD_TITLE = #boardTitle#
	 	</isNotEmpty>
	 	
	 	<isNotEmpty property="boardContent">
	 		AND BOARD_CONTENT LIKE '%' || #boardContent# || '%'
	 	</isNotEmpty>
	
	</select>

</sqlMap>			

 

8) SqlMapClientConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig      
    PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"      
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
	<!-- 
	DB와 연결하는 정보를 properties파일에 설정해 놓고 이 properties파일의
	내용을 읽어와 설정한다.
	 -->
	<properties resource="SqlMapConfig.properties" />
	
	<!-- ibatis를 처리하기 위한 환경설정 부분 -->
	<settings cacheModelsEnabled="true" enhancementEnabled="true"
		lazyLoadingEnabled="true" maxRequests="32" maxSessions="10"
		maxTransactions="5" useStatementNamespaces="true" />

	<!-- 
	VO클래스등의 이름이 패키지명까지 기술하면 길어지는데 이것을 간단히
	표시하기 위해서 alias를 지정할 수 있다.
	형식) <typeAlias alias="alias명" type="클래스의 풀네임"/>
	 -->
	<typeAlias alias="boardVO" type="kr.or.ddit.board.vo.BoardVO"/>

	<!-- 
	DB와의 연결을 처리하는 부분
	SqlMapConfig.properties에 설정해 놓은 정보를 이용하여 구성한다.
	1. SIMPLE => SimpleDataSourceFactory
		SimpleDataSource는 데이터소스를 제공하는 컨테이너가 없는 경우 connection을 제공하기 위해 기본적으로 pooling 데이터소스 구현을 제공한다. 
		이것은 iBATIS SimpleDataSource connection pooling을 기반으로 한다.
		
	2. DBCP => DbcpDataSourceFactory
	DbcpDataSourceFactory는 DataSource API를 통해 connection pooling 서비스를 제공하기 위해 DBCP를 사용한다.
	이 DataSource는 어플리케이션/웹 컨테이너가 DataSource 구현물을 제공하지 못하거나 standalone 어플리케이션을 구동할 때 이상적이다.
    
    3. JNDI => JndiDataSourceFactory
 	JndiDataSourceFactory 는 어플리케이션 컨테이너내 JNDI 컨텍스트로부터 DataSource 구현물을 가져와야 한다. 
 	이것은 어플리케이션 서버를 사용중이고 컨테이너 관리 connection pool 과 DataSource 가 제공될 때 사용한다.
 	JDBC DataSource 구현물에 접근하기 위한 표준적인 방법은 JNDI 컨텍스트를 통하여 접근하는 것이다.
	 -->
	<transactionManager type="JDBC">
		<dataSource type="SIMPLE">
		<!--
			각종 설정을 직접 기술해서 처리할 수도 있다. 
			<property name="JDBC.Driver" value="oracle.jdbc.driver.OracleDriver" />
		 -->
			<property name="JDBC.Driver" value="${driver}" />
			<property name="JDBC.ConnectionURL" value="${url}" />
			<property name="JDBC.Username" value="${username}" />
			<property name="JDBC.Password" value="${password}" />
		</dataSource>
	</transactionManager>
	
	<!-- 
	실제 처리할 SQL문은 xml문서로 따로 만든 후
	그 xml문서와 아래와 같이 연결하여 사용한다.
	형식) <sqlMap resource="경로명/파일명.xml"/> 
	-->
	<sqlMap resource="kr/or/ddit/sqlmap/board.xml"/>
</sqlMapConfig>

 

 

9) SqlMapConfig.properties (username 오라클 이름, password는 초기에 설정한 오라클 비밀번호 입력)

# SqlMapConfig.properties
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
username=
password=

'High Java > IBatis' 카테고리의 다른 글

[Java] IBatis를 이용한 CRUD 예제  (0) 2020.10.26
Comments