- Outsider's Dev Story
- 흔한 개발자의 개발 노트
- 내 아이큐 80, 너도 80, 둘이 합쳐 160 - 내…
- 조대협의 블로그
- 자바캔(Java Can Do IT) / 최범균 님
- Sangon, Han – 개발자; 읽고 생각하고 쓰고 …
- The Evolution of the Web
- NAVER D2
- Dashboard - SLiPP
- ITWorld Korea - 테크놀로지 리더를 위한 글…
- OKKY - All That Developer
- 웹Frameworks
- 오픈튜토리얼스
- 위키독스 / 온라인 책 제작 공유 플랫폼 서비스
- 블로터
- IT OnAir
- 한 처음에 / 백창92
- Divide my knowledge / 완프최
- SERI.org
Bigfat
[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 |