VO의 심화 개념, pstmt의 사용과 stmt와의 차이, 포스팅내용을 활용한 실습예제 코드 및 풀이의 내용을 포스팅 하였다.
1. ModelVO_TableDB에서의 역할
1) VO와 tableDB는 별개이다
: tableDB를 배열로 가지고 다닐 수 없어, VO에 TableDB을 담아서 들고다니기 용이하게 하는 자료형의 개념이다.
2) 로직마다에서의 VO
: VO는 DAO의 핵심 로직에 인자를 효율적으로 전달하기 위한 목적으로 사용된다. 이러한 VO는 각각의 핵심로직에서 아래와 같은 단계들을 통해 TableDB에 전달된다.
* Table 1개당 1개의 DAO(비즈니스메서드 로직)가 필요하다 *
1) VO의 set이 완료되고,
2) DAO에 해당 VO가 전달하라 명령을 내리면,
3) DAO의 인자로 main에서 Set된 VO가 정상적으로 전달되게 된다.
4) 전달된 VO를 DB에 전달하라 명령을 내리면,
5) execute문을 통해 VO를 통해 전달된 값들이 DB에 적용된다.
* 해당 로직에서 id(pk)의 변화 *
insert로직에서 진행된 결과들을 출력하게 되면 [ex) id=0, name=홍길동, point=3000 ]과 같다. 이때, pk는 java에서 다루는 것이 아니므로 0이 출력되는 것은 당연하다. 데이터가 DB에 전달되어 들어가게 됐을때 pk가 지정되고, 전달되게 되면 DB상에서는 pk가 정상적으로 증가되어 존재하게 된다. 각 단계에서의 vo현황을 알기 위해 test개념으로 진행되는 출력이고, 어차피 insert에는 출력로직 필요 없이 저장이 제대로 된 후에 select를 통해 출력할 예정이라 문제 되는 것은 없다.
2. pstmt
: pstmt는 conn.prepareStatement( )를 통해 생성하는 객체이다. 성격은 stmt와 유사하지만 분명한 차이가 있다.
stmt는 conn을 통해 tableDB와 연결한 후 execute문을 통해 SQL명령문구를 완성하여 DB에 직접 접근하여 값을 적용하는 방식이라면, pstmt는 conn을 통해 사용할 SQL명령문구와 연결한 후 연결한 SQL문에 값을 전달한 뒤 execute문을 실행시켜 전달한 값을 tableDB에 적용하는 방식이다.
이때, pstmt는 전달할 인자가 문자열이라도 작은따옴표의 사용을 생략한다.
//pstmt의 SQL컬럼
// pstmt는 ! 문자열인 인자도 '?'가 아니라 그냥 ?로 입력해야함.
final String insert="insert into member (id,name,point) values((select nvl(max(id),0)+1 from member),?,?)";
//stmt의 SQL컬럼
final String sql_insert="insert into student (snum,sname,score) values((select nvl(max(snum),0)+1 from student),'";
3. 실습예제와 풀이
: Utill class와 VO의 서식은 생략하여 첨부하였다.
1) TableDB
select * from user_tables;
create table member(
id int primary key, --순차적으로 증가하도록
name varchar(20) not null,
point int default 0
);
select * from member;
2) DAO
package class04;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class MemberDAO {
Connection conn;
PreparedStatement pstmt;
// pstmt는 문자열의 입력도 작은따옴표(' ')는 생략한다.
final String insert="insert into member (id,name,point) values((select nvl(max(id),0)+1 from member),?,?)";
final String selectOne="select * from member where id=?";
// 해당 id가 존재한다면 point+?을 진행
final String update="update member set point=point+? where id=?";
final String delete="delete from momber where id=?";
// pstmt에서는 검색을 진행할때 SQL문의 표현이 조금 상이하다.
final String selectAll="select * from member where name like '%'||?||'%'";
final String selectAll2="select * from member where point>=? order by point asc";
//[삽입]
public boolean insert(MemberVO vo) {
conn=JDBCUtill.connect();
try {
pstmt=conn.prepareStatement(insert);
// 적합한 값을 넣을 수 있다.
// 첫번째 물음표에 getname 설정하라!
pstmt.setString(1, vo.getName());
pstmt.setInt(2, vo.getPoint());
//해당 sql을 수행하겠다. 라는 의미"read, write"가 진행
pstmt.executeUpdate();//즉, 37 line에 닿아야 insert가 진행됨
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} finally {
JDBCUtill.disconnect(pstmt, conn);
}
return true;
}
// [포인트 추가]
public boolean update(MemberVO vo) {
conn=JDBCUtill.connect();
int result = 0;
try {
//sql문을 실행하고, 물음표는 잠시 대기!
pstmt = conn.prepareStatement(update);
//여기서 각 물음표에 들어갈 값 지정!
pstmt.setInt(1, vo.getPoint());
pstmt.setInt(2, vo.getId());
//이제 DB접근해서 진짜로 바꿔!
result = pstmt.executeUpdate();//반환이 int
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}finally {
JDBCUtill.disconnect(pstmt, conn);
} if(result==0) { //접근한 데이터가 0개야?
return false; //그럼 update실패
}
return true; //무사히 잘 여기까지 오면 update성공!
}
// [회원탈퇴]
public boolean delete(MemberVO vo) {
conn=JDBCUtill.connect();
int result = 0;
try {
//sql문을 실행하고, 물음표는 잠시 대기!
pstmt = conn.prepareStatement(delete);
//여기서 각 물음표에 들어갈 값 지정!
pstmt.setInt(1, vo.getId());
//이제 DB접근해서 진짜로 바꿔!
result = pstmt.executeUpdate();//반환이 int
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}finally {
JDBCUtill.disconnect(pstmt, conn);
} if(result==0) { //접근한 데이터가 0개야?
return false; //그럼 update실패
}
return true; //무사히 잘 여기까지 오면 update성공!
}
// [회원id조회]
public MemberVO selectOne(MemberVO vo) {
conn=JDBCUtill.connect();
MemberVO data=null;//검색실패시 반환할 값
try {
pstmt = conn.prepareStatement(selectOne);
pstmt.setInt(1, vo.getId());
ResultSet rs = pstmt.executeQuery();
if(rs.next()) {
data=new MemberVO();
data.setId(rs.getInt("id"));
data.setName(rs.getString("name"));
data.setPoint(rs.getInt("point"));
}
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtill.disconnect(pstmt, conn);
}
return data;
}
// [회원검색 : 이름 혹은 포인트로]
public ArrayList<MemberVO> selectAll(MemberVO vo){
ArrayList<MemberVO> datas= new ArrayList<MemberVO>();
conn=JDBCUtill.connect();
//포인트를 입력받았을때, 이름은 null이다.
//이 점을 활용하여 이름검색과 포인트검색 결과를 나누어보자
try {
if(vo.getName()!=null){//입력이 입력되었다면!
pstmt=conn.prepareStatement(selectAll);
pstmt.setString(1, vo.getName());
}else {//그게 아니라면!
pstmt=conn.prepareStatement(selectAll2);
pstmt.setInt(1, vo.getPoint());
}
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
MemberVO data = new MemberVO();
data.setId(rs.getInt("id"));
data.setName(rs.getString("name"));
data.setPoint(rs.getInt("point"));
datas.add(data);
}
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtill.disconnect(pstmt, conn);
}
return datas;
}
}
주석을 통해 코드의 해석이 가능하다.
3) main
package class04;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class App {
public static void main(String[] args) {
//dao에 접근
MemberDAO dao = new MemberDAO();
Random rand = new Random();
Scanner sc=new Scanner(System.in);
String mainMsg = "1. 가입 \n2. 검색 \n3. 회원검색 \n4. 포인트추가 \n5. 회원탈퇴 \n6. 종료";
int act;
while(true) {
System.out.println("==========");
System.out.println(mainMsg);
System.out.println("==========");
System.out.print(">>> ");
act=sc.nextInt();
if(act==1) {
System.out.print("이름입력 : ");
String name = sc.next();
MemberVO vo = new MemberVO();
vo.setName(name);
// 랜덤으로 포인트 쌓기
int randNum=rand.nextInt(3);
// 당첨시 3000포인트 지급
if(randNum==0) {
System.out.println("당첨!");
vo.setPoint(3000);
}
dao.insert(vo);
} else if(act==2) {
MemberVO vo = new MemberVO();
System.out.println("1. 이름으로 검색");
System.out.println("2. 포인트로 검색");
act=sc.nextInt();
if(act==1) {//이름으로 검색
System.out.print("검색할 이름 : ");
String name = sc.next();
vo.setName(name);
}else { //포인트로 검색
System.out.print("검색할 포인트 : ");
int point = sc.nextInt();
vo.setPoint(point);
}
ArrayList<MemberVO> datas = dao.selectAll(vo);
System.out.println("=====검색결과=====");
for(MemberVO v : datas) {
System.out.println(v);
}
System.out.println("================");
} else if(act==3) {
System.out.print("번호입력 : ");
int id = sc.nextInt();
MemberVO vo = new MemberVO();
vo.setId(id); // [10 null 0]
//로그 VO : 사용자가 입력한 값(pk정상출력, null, 0으로 조회)
vo = dao.selectOne(vo); //검색값을 주면 검색 결과를 돌려준다.
//로그 VO : 사용자의 입력에 대한 결과
if(vo==null) { //null은 오류가 아니라 그냥 검색결과가 없는것.
System.out.println("app로그 : 검색실패");
continue;
}
System.out.println("검색결과 : "+vo);
} else if(act==4) {
System.out.print("번호입력 : ");
int id=sc.nextInt();
System.out.println("포인트입력 : ");
int point = sc.nextInt();
MemberVO vo = new MemberVO();
vo.setId(id);
vo.setPoint(point);
if(!dao.update(vo)) {//리턴 없으면!
System.out.println("app로그 : 수정실패");
continue;
}// 많은 경우 수정이 완료되기에 하단배치
System.out.println("app로그 :수정완료");
} else if(act==5) {
System.out.print("번호입력 : ");
int id=sc.nextInt();
MemberVO vo = new MemberVO();
vo.setId(id);
if(!dao.delete(vo)) {//리턴 없으면!
System.out.println("app로그 :삭제실패");
continue;
}// 많은 경우 삭제가 완료되기에 하단배치
System.out.println("app로그 : 삭제완료");
} else if(act==6) {
System.out.println("app로그 : 프로그램 종료");
break;
}
}
}
}
주석을 통해 코드의 해석이 가능하다.
'DBMS' 카테고리의 다른 글
[Oracle] 웹크롤링_기초 (0) | 2022.01.24 |
---|---|
[Oracle] 트랜잭션 (0) | 2022.01.22 |
[Oracle] DB접근&MVC분리 (0) | 2022.01.20 |
[Oracle] 개요 & SQL문법 (0) | 2022.01.19 |
[Oracle] 설치와 오류 (0) | 2022.01.18 |