2017. 4. 4. 21:28ㆍJava/web
싱글톤 패턴(Singleton pattern)을 이용하여 레코드를 삽입, 조회해보자
게시판 구현에 필요한 오라클 데이터베이스 접근을 싱글톤 패턴을 이용해 구현해보자. 싱글톤 패턴은 동일한 자원이 불필요하게 여러 개 만들어질 필요가 없을 때 주로 사용한다.
우선 게시글에 대한 테이블, 시퀀스를 생성하자.
--게시판(Bulletin Board System) 테이블 생성 CREATE TABLE BBS( ARTICLE_NUMBER NUMBER PRIMARY KEY, ID VARCHAR2(15) NOT NULL, TITLE VARCHAR2(15) NOT NULL, CONTENT CLOB NOT NULL, GROUP_ID NUMBER NOT NULL, DEPTH NUMBER NOT NULL, POS NUMBER NOT NULL, --position, 게시글 순서를 조정 HIT NUMBER NOT NULL, --조회수 WRITE_DATE DATE NOT NULL, FILE_NAME VARCHAR2(300) ); --시퀀스 생성 CREATE SEQUENCE BBS_SEQ START WITH 1 INCREMENT BY 1;
이제 계층 간의 데이터 교환을 위해 DTO(Data Transfer Object, 또는 VO, Value Object) 클래스를 만들자. DTO클래스의 멤버변수들은 private으로 제한하여 메서드를 통해서만 접근할 수 있도록 하였다. alt+shift+S를 눌러 Generate Getters and Setters와 Generate toString()을 선택해 메서드를 편리하게 생성할 수 있다.
package com.edu.bbs; import java.sql.Timestamp; public class BBSDto { private int articleNumber; private String id; private String title; private String content; private int groupId; private int depth; private int pos; private int hit; private Timestamp writeDate; // 추후 String으로 변경 private String fileName; public int getArticleNumber() { return articleNumber; } public void setArticleNumber(int articleNumber) { this.articleNumber = articleNumber; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public int getGroupId() { return groupId; } public void setGroupId(int groupId) { this.groupId = groupId; } public int getDepth() { return depth; } public void setDepth(int depth) { this.depth = depth; } public int getPos() { return pos; } public void setPos(int pos) { this.pos = pos; } public int getHit() { return hit; } public void setHit(int hit) { this.hit = hit; } public Timestamp getWriteDate() { return writeDate; } public void setWriteDate(Timestamp writeDate) { this.writeDate = writeDate; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } @Override public String toString() { return "BBSDto [articleNumber=" + articleNumber + ", id=" + id + ", title=" + title + ", content=" + content + ", groupId=" + groupId + ", depth=" + depth + ", pos=" + pos + ", hit=" + hit + ", writeDate=" + writeDate + ", fileName=" + fileName + "]"; } }
오라클 데이터베이스 커넥션을 구현한 클래스다. 오라클 외에도 다른 DB를 사용할 수 있기 때문에 따로 클래스화하자. 싱글톤 패턴은 코드 내에 주석을 참고하자. getConnection메서드의 파라미터들은 각자 데이터베이스 접속이름, 비밀번호에 맞게 변경해주자.
package com.edu.bbs; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * OracleDBConnector.java * Oracle Connection을 구현한 클래스 * 여러 데이터베이스 사용을 위해 커넥션을 클래스로 분리한다. */ public class OracleDBConnector { // private static OracleDBConnector orclDbc = new OracleDBConnector(); // 1.바로 메모리 할당하는 방법 private static OracleDBConnector orclDbc; // 외부에서의 인스턴스화를 막는다. private OracleDBConnector() {} // OracleDBConnector 인스턴스를 얻는 방법은 getInstance()메서드로 호출하는 방법뿐이다. public static OracleDBConnector getInstacne() { if (orclDbc == null) { orclDbc = new OracleDBConnector(); // 2.메모리에 할당되지 않았을 때 할당하는 방법 } return orclDbc; } public Connection getConnection() throws ClassNotFoundException, SQLException { Class.forName("oracle.jdbc.driver.OracleDriver"); // core.log를 사용하게되면 쿼리 결과를 콘솔에 찍을 수 있다. // Class.forName("core.log.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:XE"; Connection conn = DriverManager.getConnection(url, "Kyou", "1234"); return conn; } }
DB에서 조회, 삽입 등 데이터를 조작하는 DAO(Data Access Object)클래스를 구현한다. insertArticle()메서드는 게시글 하나를 삽입하고, selectArticle()메서드는 게시글 하나를 조회하는 기능을 한다.
package com.edu.bbs; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; /** * BBSOracleDao.java * DB를 사용해 데이터를 조회하거나 조작하는 기능을 구현한 클래스 * 일반, 공지게시판 등 재사용성을 늘리기 위해 클래스로 분리한다. */ public class BBSOracleDao { private static BBSOracleDao bbsOracleDao; private OracleDBConnector orclDbc = OracleDBConnector.getInstacne(); Connection conn; PreparedStatement pstmt; ResultSet rs; StringBuffer query; BBSDto article; ArrayList<BBSDto> articles; private BBSOracleDao() {} public static BBSOracleDao getInstance() { if(bbsOracleDao == null) { bbsOracleDao = new BBSOracleDao(); } return bbsOracleDao; } // synchronized, 한 명의 글쓰기를 처리한 후 다른 사람의 글쓰기를 처리해야 한다. public synchronized int insertArticle(BBSDto article) throws ClassNotFoundException, SQLException { conn = orclDbc.getConnection(); query = new StringBuffer(); query.append("INSERT INTO bbs "); query.append("VALUES(bbs_seq.nextval, ?, ?, ?, bbs_seq.currval, 0, 0, 0, sysdate, ?)"); pstmt = conn.prepareStatement(query.toString()); // parameterIndex는 쿼리문의 ? 순서대로 적어주며, 1부터 시작한다. pstmt.setString(1, article.getId()); pstmt.setString(2, article.getTitle()); pstmt.setString(3, article.getContent()); pstmt.setString(4, article.getFileName()); int result = pstmt.executeUpdate(); disconnect(); return result; } public BBSDto selectArticle(String articleNumber) throws ClassNotFoundException, SQLException { conn = orclDbc.getConnection(); query = new StringBuffer(); query.append("SELECT * FROM bbs WHERE article_number = ?"); pstmt = conn.prepareStatement(query.toString()); pstmt.setString(1, articleNumber); rs = pstmt.executeQuery(); if(rs.next()) { article = new BBSDto(); article.setArticleNumber(rs.getInt("article_number")); article.setId(rs.getString("id")); article.setTitle(rs.getString("title")); article.setDepth(rs.getInt("depth")); article.setContent(rs.getString("content")); article.setHit(rs.getInt("hit")); article.setGroupId(rs.getInt("group_id")); article.setPos(rs.getInt("pos")); article.setWriteDate(rs.getTimestamp("write_date")); article.setFileName(rs.getString("file_name")); } disconnect(); return article; } public void disconnect() throws SQLException { if(rs != null) { rs.close(); } pstmt.close(); conn.close(); } }
main메서드에서 게시글을 삽입하고 첫 번째 게시글을 조회하여 콘솔에 보이도록 해보자. ARTICLE_NUMBER 컬럼의 데이터 타입이 NUMBER인데도 파라미터를 String으로 던져주고 있다. 오라클11g(10부터였나)는 내부적으로 숫자형 문자를 숫자로 변환해주기 때문에 가능하다.
package com.edu.bbs; public class DBTest { public static void main(String[] args) { BBSDto article = new BBSDto(); article.setId("kim"); article.setTitle("첫 번째 게시글 제목"); article.setContent("첫 번째 게시글 내용"); try { if(BBSOracleDao.getInstance().insertArticle(article) == 1) { System.out.println("레코드 삽입이 성공하였습니다."); } else { System.out.println("레코드 삽입이 실패하였습니다."); } } catch (Exception e) { e.printStackTrace(); } try { System.out.println(BBSOracleDao.getInstance().selectArticle("1").toString()); } catch (Exception e) { e.printStackTrace(); } } }
[쉽게 배우는 소프트웨어 공학 singleton 패턴 참고]
[DAO / VO / DTO 란? 참고]
'Java > web' 카테고리의 다른 글
[Web] 리스트 화면 만들기 (게시판 구현) (0) | 2017.04.06 |
---|---|
[Web] 글쓰기 화면 만들기 (게시판 구현) (0) | 2017.04.05 |
[Web] 서블릿 생성하기(애노테이션) (0) | 2017.03.24 |
[Web] 서블릿 생성하기(web.xml) (0) | 2017.03.22 |
[Web] 톰캣이 웹 애플리케이션을 실행하는 순서 (0) | 2017.03.21 |