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 |