BOARD 테이블과 관련된 비즈니스 컴포넌트 구성
- BoardVO
- BoardDAO
- BoardService
- BoardServiceImpl
오라클DB를 이용한다.
Value Object - 레이어와 레이어 사이에서 관련 데이터를 한꺼번에 주고받을 목적으로 사용하는 클래스. DTO(Data Transfer Object)라고도 한다.
여기서는 롬복을 이용해 Getter, Setter, ToString 메소드를 선언한다.
pom.xml에 다음을 추가한다.
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
package com.springbook.biz.board;
import java.sql.Date;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
//VO (Value Object)
@Getter
@Setter
@ToString
public class BoardVO {
private int seq;
private String title;
private String writer;
private String content;
private Date regDate;
private int cnt;
}
pom.xml에 다음을 추가한다.
(repository는 dependency와 별개로 추가해야 함에 주의한다)
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>http://www.datanucleus.org/downloads/maven2/</url>
</repository>
</repositories>
<dependencies>
<!-- oracle driver -->
<dependency>
<groupId>oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
모든 DAO 클래스에서 공통으로 사용할 JDBCUtil 클래스를 작성해 Connection 획득과 해제 작업을 공통으로 처리한다.
package com.springbook.biz.common;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCUtil {
public static Connection getConnection() {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
return DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "sqs", "1234");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void close(PreparedStatement stmt, Connection conn) {
if (stmt != null) {
try {
if (!stmt.isClosed())
stmt.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
stmt = null;
}
}
if (conn != null) {
try {
if (!conn.isClosed())
conn.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
conn = null;
}
}
}
public static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {
if (rs != null) {
try {
if (!rs.isClosed())
rs.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
rs = null;
}
}
if (stmt != null) {
try {
if (!stmt.isClosed())
stmt.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
stmt = null;
}
}
if (conn != null) {
try {
if (!conn.isClosed())
conn.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
conn = null;
}
}
}
}
데이터베이스 연동을 담당하는 클래스. CRUD 메소드가 구현되어야 한다. 오라클 JDBC드라이버인 ojdbc가 필요하다.
클래스 객체를 스프링 컨테이너가 생성할 수 있도록 클래스 선언부에 @Repository 어노테이션을 설정. DAO클래스에는 @Component보다 @Repository를 사용하는 것이 적합하다.
package com.springbook.biz.board.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.common.JDBCUtil;
//DAO(Data Access Object)
@Repository("boardDAO")
public class BoardDAO {
//JDBC 관련 변수
private Connection conn = null;
private PreparedStatement stmt = null;
private ResultSet rs = null;
//SQL 명령어들
private final String BOARD_INSERT = "insert into board(seq, title, writer, content) values((select nvl(max(seq), 0)+1 from board),?,?,?)";
private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
private final String BOARD_DELETE = "delete board where seq=?";
private final String BOARD_GET = "select * from board where seq=?";
private final String BOARD_LIST = "select * from board order by seq desc";
//CRUD 기능의 메소드 구현
//글 등록
public void insertBoard(BoardVO vo) {
System.out.println("===> JDBC로 insertBoard() 기능 처리");
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_INSERT);
stmt.setString(1, vo.getTitle());
stmt.setString(2, vo.getWriter());
stmt.setString(3, vo.getContent());
stmt.executeUpdate();
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(stmt, conn);
}
}
//글 수정
public void updateBoard(BoardVO vo) {
System.out.println("===> JDBC로 updateBoard() 기능 처리");
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_UPDATE);
stmt.setString(1, vo.getTitle());
stmt.setString(2, vo.getContent());
stmt.setInt(3, vo.getSeq());
stmt.executeUpdate();
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(stmt, conn);
}
}
//글 삭제
public void deleteBoard(BoardVO vo) {
System.out.println("===> JDBC로 deleteBoard() 기능 처리");
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_DELETE);
stmt.setInt(1, vo.getSeq());
stmt.executeUpdate();
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(stmt, conn);
}
}
//글 상세 조회
public BoardVO getBoard(BoardVO vo) {
System.out.println("===> JDBC로 getBoard() 기능 처리");
BoardVO board = null;
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_GET);
stmt.setInt(1, vo.getSeq());
rs = stmt.executeQuery();
if(rs.next()) {
board = new BoardVO();
board.setSeq(rs.getInt("SEQ"));
board.setTitle(rs.getString("TITLE"));
board.setWriter(rs.getString("WRITER"));
board.setContent(rs.getString("CONTENT"));
board.setRegDate(rs.getDate("REGDATE"));
board.setCnt(rs.getInt("CNT"));
}
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(rs, stmt, conn);
}
return board;
}
//글 목록 조회
public List<BoardVO> getBoardList(BoardVO vo){
System.out.println("===> JDBC로 getBoardList() 기능 처리");
List<BoardVO> boardList = new ArrayList<BoardVO>();
try {
conn = JDBCUtil.getConnection();
stmt = conn.prepareStatement(BOARD_LIST);
rs = stmt.executeQuery();
while(rs.next()) {
BoardVO board = new BoardVO();
board.setSeq(rs.getInt("SEQ"));
board.setTitle(rs.getString("TITLE"));
board.setWriter(rs.getString("WRITER"));
board.setContent(rs.getString("CONTENT"));
board.setRegDate(rs.getDate("REGDATE"));
board.setCnt(rs.getInt("CNT"));
boardList.add(board);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.close(rs, stmt, conn);
}
return boardList;
}
}
만들고 나니 BoardDAO와 같은 폴더라서 biz.board폴더로 옮겨뒀다.
인터페이스 생성 후 BoardDAO에 자동으로 추가된
implements BoardService부분은 지워야 한다!
package com.springbook.biz.board;
import java.util.List;
import com.springbook.biz.board.BoardVO;
public interface BoardService {
//CRUD 기능의 메소드 구현
//글 등록
void insertBoard(BoardVO vo);
//글 수정
void updateBoard(BoardVO vo);
//글 삭제
void deleteBoard(BoardVO vo);
//글 상세 조회
BoardVO getBoard(BoardVO vo);
//글 목록 조회
List<BoardVO> getBoardList(BoardVO vo);
}
BoardService 인터페이스를 구현한 BoardServiceImpl 클래스.
BoardService 인터페이스의 모든 추상 메소드를 Overriding오버라이딩
클래스 선언부에 객체 생성을 위한 @Service 선언
클라이언트 프로그램에서 boardService라는 이름으로 객체 요청할 수 있도록 아이디 설정
DB연동이 포함된 비즈니스 로직 처리를 위해 BoardDAO타입의 객체를 멤버변수로 가짐 - 이 변수에 BoardDAO타입의 객체를 의존성 주입하기 위해 @Autowired 설정
package com.springbook.biz.board.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
@Service("boardService")
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardDAO boardDAO;
@Override
public void insertBoard(BoardVO vo) {
boardDAO.insertBoard(vo);
}
@Override
public void updateBoard(BoardVO vo) {
boardDAO.updateBoard(vo);
}
@Override
public void deleteBoard(BoardVO vo) {
boardDAO.deleteBoard(vo);
}
@Override
public BoardVO getBoard(BoardVO vo) {
return boardDAO.getBoard(vo);
}
@Override
public List<BoardVO> getBoardList(BoardVO vo) {
return boardDAO.getBoardList(vo);
}
}
다음 코드를 추가
<context:component-scan base-package="com.springbook.biz"></context:component-scan>
BoardServiceClient 클래스를 src/test/java/com/springbook/biz 폴더에 작성한다.
package com.springbook.biz;
import java.util.List;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;
public class BoardServiceClient {
public static void main(String[] args) {
//1. Spring 컨테이너를 구동한다.
AbstractApplicationContext container = new GenericXmlApplicationContext("applicationcontext.xml");
//2. Spring 컨테이너로부터 BoardServiceImpl 객체를 Lookup한다.
BoardService boardService = (BoardService) container.getBean("boardService");
//3. 글 등록 기능 테스트
BoardVO vo = new BoardVO();
vo.setTitle("임시 제목");
vo.setWriter("홍길동");
vo.setContent("임시 내용........");
boardService.insertBoard(vo);
//4. 글 목록 검색 기능 테스트
List<BoardVO> boardList = boardService.getBoardList(vo);
for (BoardVO board : boardList) {
System.out.println("---> " + board.toString());
}
//5. Spring 컨테이너 종료
container.close();
}
}
파일을 제대로 import하지 못하는 에러가 났다.
BoardService cannot be resolved to a type
test폴더 밑에 com.springbook.biz.board 패키지를 만들지 않고 파일만 생성해서 나타난 오류였다.
===> JDBC insertBoard() 기능 처리
DB 연결 완료
실행 결과가 딱 이렇게만 나왔다.
롬복이 ToString 처리를 제대로 못한 것 같다.
BoardVO에서 lombok의 @ToString을 지우고 Source > Generate to ToString을 사용해 다시 만들었다.
그래도 안 된다.
이유를 알아냈다. 오라클DB에서 테이블 생성하고 나서 커밋을 안해서였다...