Oracle DB를 연결해서 DB에 있는 데이터를 조회해보자.
package com.util;
import java.net.URL;
import java.sql.*;
//공통코드 작성해 보기
//반복되는 코드 줄이기
//메소드는 슬림(양이 적게)하게 하나의 책임만 진다 - 재사용성이 좋다.
//DB서버는 하나이고 하나의 서버를 여러 개발자들이 바라본다
//하나의 객체를 가지고 공유하자(싱글톤패턴 - Sprint지원 - 프레임워크)
//클래스선언에 static붙임 - 얕은복사.
//모두 인터페이스이다. (Connection,PreparedStatement,ResultSet) - 결정할 수 없다.
//왜요? 디바이스마다 각각 다르게 동작해야한다. - 결정할 수 없다. - 구현체 클래스가 한다.
//아래 인터페이스는 모두 메소드로 객체 생성함.
public class DBConnectionMgr {
static DBConnectionMgr dbMgr =null;
//서버(정보제공측) - 클라이언트(제공된 정보를 활용) -> 2-iter
//서버 - 미들웨어서버 - 클라이언트 -> 3-iter or multi-iter 라고도 불린다.
//java.sql.* 혹은 javax.sql.* 참조함.
Connection con; //
PreparedStatement pstmt; //동적쿼리
ResultSet rs; //Cursor조작하는 API를 제공한다.
public final static String _Driver ="oracle.jdbc.driver.OracleDriver";
public final static String _URL ="jdbc:oracle:thin:@localhost:1522:orcl";
public final static String _User ="Scott";
public final static String _Pass ="tiger";
//메소드를 활용하여 객체를 생성하기 - 세련된 코드 - 싱글톤 패턴
public static DBConnectionMgr getInstance() {
if(dbMgr==null) {
dbMgr=new DBConnectionMgr();
}
return dbMgr;
}
public Connection getConnection() {
try {
Class.forName(_Driver);
con = DriverManager.getConnection(_URL, _User, _Pass);
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
//사용한 자원 반납하기 - 이종간에 연계하는 코드 작성.
//사용자 자원을 닫을 때는 생성된 역순으로 닫는다.
//생략하면 JVM의 가비지컬렉터가 대신 해준다. -명시적으로 구현하는 것을 권장함
//JDBC API - 순수한코드 -> MyBatis 사용 -> Hibernate
//insert,update,delete -> Connection, PreparedStatement
//select -> Connection, PreparedStatement, ResultSet
public void freeConnection(Connection con,PreparedStatement pstmt,ResultSet rs) {
try{
if(rs != null) {
rs.close();
}
if(pstmt != null) {
pstmt.close();
}
if(con != null) {
con.close();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
VO의 특징
package jdbc.book;
//Getter and Setter를 이용해서 VO 설계해보기
//그러나 상황에 따라 사용하지 않고 공부하기.
public class BookVO1 {
private int b_no;
private String b_name;
private String b_author;
private String b_publish;
private String b_info;
//여기서 파일 업로드 처리는 하지 않습니다. 그래서 이미지 이름만 저장
private String b_img;
public BookVO1() {}
public BookVO1(int b_no, String b_name, String b_author, String b_publish, String b_info, String b_img) {
this.b_no = b_no;
this.b_name = b_name;
this.b_author = b_author;
this.b_publish = b_publish;
this.b_info = b_info;
this.b_img = b_img;
}
public String getB_author() {
return b_author;
}
public void setB_author(String b_author) {
this.b_author = b_author;
}
public int getB_no() {
return b_no;
}
public void setB_no(int b_no) {
this.b_no = b_no;
}
public String getB_name() {
return b_name;
}
public void setB_name(String b_name) {
this.b_name = b_name;
}
public String getB_publish() {
return b_publish;
}
public void setB_publish(String b_publish) {
this.b_publish = b_publish;
}
public String getB_info() {
return b_info;
}
public void setB_info(String b_info) {
this.b_info = b_info;
}
public String getB_img() {
return b_img;
}
public void setB_img(String b_img) {
this.b_img = b_img;
}
}
package jdbc.book;
import lombok.AllArgsConstructor;
import lombok.Generated;
import lombok.NoArgsConstructor;
import lombok.Setter;
//그러나 상황에 따라 사용하지 않고 공부하기.
@Setter
@Generated
@AllArgsConstructor
@NoArgsConstructor
public class
BookVO {
private int b_no;
private String b_name;
private String b_author;
private String b_publish;
private String b_info;
//여기서 파일 업로드 처리는 하지 않습니다. 그래서 이미지 이름만 저장
private String b_img;
}
select b_no from book152
파싱(Parsing) - SQL문에 문법적으로 문제가 있는지 확인한다.
실행 계획 생성(Execution Plan Generation) - DBMS가 실행계획을 세운다.
옵티마이저(Optimizer) - DBMS는 실행 계획을 세우기 위해 DBMS는 옵티마이저를 사용하며 여러가지 실행 계획을 시뮬레이션하여 가장 비용이 적은(빠르고 효율적인) 계획을 선택한다.
실행 (Execution) - 최적의 계획이 결정되면 DBMS는 쿼리를 실행합니다.
결과 반환 (Fetching Results) - 실행 결과는 사용자에게 반환됩니다.
open -> cursor -> fetch -> close
package jdbc.book;
//MVC패턴 - 데이터와 관련된 것을 Model 계층이다.
import com.util.DBConnectionMgr;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class BookDao {
//Spring프레임워크가 기본적으로 객체 라이프사이클 관리하는 메커니즘
DBConnectionMgr dbMgr = DBConnectionMgr.getInstance(); //싱글톤 패턴
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
BookApp bookApp = null;
public BookDao(BookApp bookApp){
this.bookApp = bookApp;
}
public BookDao(){}
/*********************************************************
* 도서 목록 조회 및 상세조회 구현
* SELECT b_no,b_name,b_author,b_publish,b_info,b_img
* FROM book152
* where b_no = ? 1건 조회하기
* SELECT b_no,b_name,b_author,b_publish,b_info,b_img
* FROM book152 전체 조회
* @param pbvo
* @return List<BookVO> : BookVO가 한 건만 담을 수 있다.
* 한 건이면 bList.size() = 1 이면 한 건이다.
* bList.size() > 1 이면 여러 건이다.
***********************************************************/
public List<BookVO> getBookList(BookVO pbvo){
System.out.println("getBookList호출 성공"+ pbvo.getB_no());
List<BookVO> bList = new ArrayList<>();
System.out.println(bList.size());
StringBuilder sql =new StringBuilder(); //String은 원본이 바뀌지 않아서 메모리에 대한 누수가 있다.
sql.append("select b_no,b_name,b_author,b_publish,b_info,b_img");
sql.append(" from book152");
if(pbvo.getB_no() > 0){
sql.append(" where b_no = ?");
}
try{
conn = dbMgr.getConnection();
pstmt = conn.prepareStatement(sql.toString());
if(pbvo.getB_no() > 0) {
pstmt.setInt(1, pbvo.getB_no());
}
rs = pstmt.executeQuery();
BookVO bvo = null;
while(rs.next()){
bvo = new BookVO();
bvo.setB_no(rs.getInt("b_no"));//도서일련번호
bvo.setB_name(rs.getString("b_name"));//도서명
bvo.setB_author(rs.getString("b_author"));//저자명
bvo.setB_publish(rs.getString("b_publish"));//출판사
bvo.setB_info(rs.getString("b_info"));//도서 소개
bvo.setB_img(rs.getString("b_img"));//도서이미지
bList.add(bvo);
}
} catch (SQLException e) {
System.out.println(sql.toString());
} catch (Exception e) {
e.printStackTrace();
}
finally{//예외가 발생하더라도 무조건 실행된다.
//사용한 자원 반납하기 - 생성된 역순으로 해준다.
//생략하면 처리는 되지만 명시적으로 처리하는 것이다. - 자바 튜닝
dbMgr.freeConnection(conn, pstmt, rs);
}
System.out.println(bList.size());
return bList;
}
// public static void main(String[] args) {
// BookDao bookDao = new BookDao(new BookApp());
// System.out.println(bookDao.getBookList(new BookVO()));
// }
//
/*******************************************************
* 도서 삭제 구현하기
* DELETE FROM book152 WHERE b_no = ?
* @param //bvo or int b_no
* @return int - 1이면 삭제 성공 / 0이면 삭제 실패
*********************************************************/
public int bookDelete(int b_no){
int result = -1; //1이면 삭제 성공. 0이면 삭제 실패, 그래서 초기값을 -1로 한다.
StringBuilder sql =new StringBuilder();
sql.append("delete from book152 where b_no= ?");
try{
conn = dbMgr.getConnection();
pstmt = conn.prepareStatement(sql.toString());
pstmt.setInt(1, b_no); //b_no = ? 에 들어가는 번호
result = pstmt.executeUpdate();
} catch (SQLException e) {
//쿼리문에 부적합한 식별자(컬럼명 오타), 테이블이나 뷰(오브젝트-select문 금융) 이름이 없습니다.
System.out.println(sql.toString());
} catch (Exception e) {
e.printStackTrace(); //에러메시지도 stack에 히스토리를 가짐. 출력함
}
return result; //성공이면 1 실패이면 0
}
/*******************************************************************
* 도서 정보 수정하기
* UPDATE book152
* SET b_name = ?
* ,b_author = ?
* ,b_publish = ?
* WHERE b_no = ?
* @param bvo
* @return
*/
public int bookUpdate(BookVO bvo){
int result = -1; //1이면 수정 성공. 0이면 수정 실패, 그래서 초기값을 -1로 한다.
conn = dbMgr.getConnection();
StringBuilder sql =new StringBuilder();
sql.append(" UPDATE book152 set b_name=?,b_author=?,b_publish=?,b_info=?,b_img=?");
sql.append(" where b_no = ?");
try{
pstmt = conn.prepareStatement(sql.toString());
pstmt.setString(1, bvo.getB_name());
pstmt.setString(2, bvo.getB_author());
pstmt.setString(3, bvo.getB_publish());
pstmt.setString(4, bvo.getB_info());
pstmt.setString(5, bvo.getB_img());
pstmt.setInt(6, bvo.getB_no());
result = pstmt.executeUpdate();
}catch (SQLException e){
System.out.println(sql.toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
finally {
dbMgr.freeConnection(conn, pstmt);
}
return result;
}
//BookVO를 사용하지 않으면 파라미터 변수(컬럼명)를 다 주어야한다.
// public int bookUpdate(int b_no,String b_name,String b_author,String b_publish){
// return 1;
// }
/****************************************************************
* 도서 정보 넣기
* INSERT INTO book152(b_no,b_name,b_author,b_publish) VALUES(?,'?')
* @param bvo
* @return
*****************************************************************/
public int bookInsert(BookVO bvo){
int result = -1; //1이면 삽입 성공. 0이면 삽입 실패, 그래서 초기값을 -1로 한다.
StringBuilder sql =new StringBuilder();
sql.append("insert into book152 values(seq_book152_no.nextval,?,?,?,?,?)");
int i = 1;
try{
conn = dbMgr.getConnection();
pstmt = conn.prepareStatement(sql.toString());
//? 자리를 채우는 값을 설정할 때는 1번 부터 입니다.
//컬럼이 추가되거나 컬럼의 순서가 바뀌면 숫자를 일일이 바꿔야하니까
//번호 대신에 변수로 처리합니다. - 후위 연산자. -먼저 대입 나중에 증가
//변수 i의 초기값이 0이면 ++i가 맞고 초기값을 1로 하면 i++이 맞다.
pstmt.setString(i++,bvo.getB_name());
pstmt.setString(i++,bvo.getB_author());
pstmt.setString(i++,bvo.getB_publish());
pstmt.setString(i++,bvo.getB_info());
pstmt.setString(i++,bvo.getB_img());
result = pstmt.executeUpdate();
}catch (SQLException e){
System.out.println(sql.toString());
}
catch (Exception e){
e.printStackTrace();
}finally {
dbMgr.freeConnection(conn, pstmt);
}
return result;
}
}
package jdbc.book;
import javax.swing.*;
import java.util.List;
//main 메소드에 코드 많이 작성하는 거 금지
public class BookDaoTest {
BookDao bookDao = new BookDao();
JFrame frame = new JFrame();
public int bookDelete(int b_no) {
int result = -1;
result = bookDao.bookDelete(b_no);
if (result == 1) {
System.out.println("1개 row가 삭제되었습니다"+result);
}
else {
System.out.println("삭제가 실패되었습니다."+result);
}
return result;
}
public void getBookListTest(){
BookDao bookDao = new BookDao();
BookVO bookVO = new BookVO();
bookVO.setB_no(0);
List<BookVO> bookList = bookDao.getBookList(bookVO);
//b_no가 0이면 where절이 추가되지 않아서 전체 조회가 된다.
//b_no가 1이면 where절이 반영되니까 한 건이 조회가 된다.
//b_no가 2이면 where절이 반영되니까 한 건이 조회가 된다.
//b_no가 3이면 where절이 반영되니까 한 건이 조회가 된다.
for (BookVO vo : bookList) {
System.out.println(vo.getB_no());
System.out.println(vo.getB_name());
System.out.println(vo.getB_author());
System.out.println(vo.getB_publish());
System.out.println(vo.getB_info());
}
}
// public void bookInsertTest(String b_name, String b_author, String b_publish, String b_info,String b_jpg) {
// int result = -1;
// BookVO bookVO = new BookVO();
// BookDao bookDao = new BookDao();
//
// bookVO.setB_name(b_name);
// bookVO.setB_author(b_author);
// bookVO.setB_publish(b_publish);
// bookVO.setB_info(b_info);
// bookVO.setB_img(b_jpg);
//
// result = bookDao.bookInsert(bookVO);
//
// if (result > 0) {
// System.out.println("도서 삽입 성공");
// } else {
// System.out.println("도서 삽입 실패");
// }
// } //BookVO의 생성자를 활용하여 데이터를 넣는다.
public static void main(String[] args) {
BookDaoTest test = new BookDaoTest();
int result = -1;
result = test.bookDelete(8);
if (result == 1) {
JOptionPane.showMessageDialog(test.frame,"삭제 성공하였습니다.");
test.getBookListTest();
}
else{
JOptionPane.showMessageDialog(test.frame,"삭제 실패하였습니다.");
}
result = -1;
BookVO bookVO = new BookVO(0,"책제목5","장보고","내용2","정보2","6.jpg");
result = test.bookDao.bookInsert(bookVO); //생성자를 활용하여서 데이터를 넣는다.
if (result == 1) {
JOptionPane.showMessageDialog(test.frame,"삽입 성공하였습니다.");
}
else{
JOptionPane.showMessageDialog(test.frame,"삽입 실패하였습니다.");
}
bookVO = new BookVO(4,"책제목 5","세종대왕","내용55","정보88","7.jpg");
result = test.bookDao.bookUpdate(bookVO);
if (result == 1) {
JOptionPane.showMessageDialog(test.frame,"업데이트 성공하였습니다.");
}
else{
JOptionPane.showMessageDialog(test.frame,"업데이트 실패하였습니다.");
}
}
}
UPDATE문 실행 업데이트 성공

결과
