Simplify JDBC of OracleSQL to JSON
OracleSQL Process
create table shop(num number(3) primary key,
sangpum varchar2(30),
color varchar2(20),
price number(5),imgname varchar2(50));
insert into shop values(seq_1.nextval,'빨간가방','red',78000,'../image/logoImg/bag04.png');
- oracle 통해 DB에 테이블(shop) 생성
- 아래는 생성된 테이블의 결과
- DBConnect를 위한 클래스와 메서드 가져오기(생략/0801에서 찾기)
JSP Process
<%@page import="org.json.simple.JSONArray"%>
<%@page import="org.json.simple.JSONObject"%>
<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@page import="oracle_db.DBConnect"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
DBConnect db=new DBConnect();
Connection conn=db.getConnection();
Statement stmt=null;
ResultSet rs=null;
String sql="select * from shop order by num";
%>
- DB의 모든 데이터를 json의 배열에 담아야 하므로 select * 명령문 사용
- 이를 위해 ResultSet 클래스 필요
try{
stmt=conn.createStatement();
rs=stmt.executeQuery(sql);
JSONArray arr=new JSONArray();
while(rs.next())
{
String num=rs.getString("num");
String sangpum=rs.getString("sangpum");
String color=rs.getString("color");
String price=rs.getString("price");
String imgname=rs.getString("imgname");
JSONObject ob=new JSONObject();
ob.put("num", num);
ob.put("sangpum", sangpum);
ob.put("color", color);
ob.put("price", price);
ob.put("imgname", imgname);
//array에 추가
arr.add(ob);
}%>
<%=arr.toString() %> //try~catch내에 JSONObject선언했으므로 해당지역 내에서만 호출가능
<%}catch(SQLException e){
}
%>
- Statement와 ResultSet 클래스 생성
- 기존 방식(0801)으로 DB의 데이터를 json의 배열로 변환하기 위해서는 “”(따옴표)와 \”(escape 문자)를 이용해 배열의 구성을 수작업으로 구현해야 함
- 이를 간단히 처리해주는 메서드인 JSONObject()와 JSONArray() 생성
- JSONObject()는 인자 값으로 (배열의 원소 내 속성, 속성 값)을 받으며, 코드는 (참조 변수).put();
- JSONArray()는 인자 값으로 JSONObject()(ob)를 받으며, 코드는 (참조 변수).add();
- toString() 함수로, 생성된 배열 형식을 문자열로 변환
- 결과적으로 json 형식에 맞는 배열과 원소를 문자열로 구현
Call Date Type from OracleSQL to JSON
try{
stmt=conn.createStatement();
rs=stmt.executeQuery(sql);
JSONArray arr=new JSONArray();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
while(rs.next())
{
String day=sdf.format(rs.getTimestamp("gaipday")); //getTimestamp(),getDate() 같은기능
JSONObject ob=new JSONObject();
ob.put("gaipday", day);
//array에 추가
arr.add(ob);
- Date 타입의 데이터는 getString으로 호출할 시 문자열로만 인식
- SimpleDateFormat() 매서드는 인자 값으로 Date 타입의 자료형 요구
- getTimeStamp() 혹은 getDate()는 전달 값을 Date 타입으로 전송(둘은 거의 같은 기능)
CRUD within JSP
create table sinsang(num number(5) primary key,
name varchar2(20),
addr varchar2(30),
sdate date);
- num, name, addr, sdate 4개의 속성을 가진 DB 테이블 생성(아직 데이터는 공백)
DTO(Data Transfer Object)
import java.sql.Timestamp;
public class SinsangDto {
private String num;
private String name;
private String addr;
private Timestamp sdate;
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public Timestamp getSdate() {
return sdate;
}
public void setSdate(Timestamp sdate) {
this.sdate = sdate;
}
}
- SinsangDto는 데이터 교환만을 위한 객체로, 로직 없이 데이터 객체만 존재(setter, getter만)
- DB 컬럼 값 데이터를 각각 멤버 변수로 선언
DAO(Data Access Object)
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Vector;
import oracle.db.DBConnect;
public class SinsangDao {
DBConnect db=new DBConnect();
}
- import 받은 클래스와 전역에 걸쳐 jdbc에 사용할 DBConnect 클래스 생성
public void insertSinsang(SinsangDto dto) {
Connection conn=db.getConnection();
PreparedStatement pstmt=null;
String sql="insert into sinsang values(seq_1.nextval,?,?,sysdate)";
try {
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, dto.getName());
pstmt.setString(2, dto.getAddr());
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.dbClose(pstmt, conn);
}
}
- 초기 DB 값이 공백이므로 insert가 우선 필요
- DTO 클래스(SinsangDto) 전체 멤버 값(각 컬럼 값)을 받아와 처리하기 위해 클래스 자체를 메서드의 인자 값으로 설정
- num과 sdate 컬럼은 자동 생성 데이터를 가지므로 insert 필요 없음(name, addr 컬럼만 insert)
- PrepareStatement 클래스를 이용해 ?로 insert 명령문 작성
- PrepareStatement의 setString() 함수로 insert 명령문 완성
- execute() 혹은 executeUpdate() 함수로 OracleSQL에서 명령문 실행
public Vector<SinsangDto> getAllDatas(){
Vector<SinsangDto> list=new Vector<SinsangDto>();
Connection conn=db.getConnection();
PreparedStatement pstmt=null;
ResultSet rs=null;
String sql="select * from sinsang order by num";
try {
pstmt=conn.prepareStatement(sql);
rs=pstmt.executeQuery();
while(rs.next())
{
SinsangDto dto=new SinsangDto();
dto.setNum(rs.getString("num"));
dto.setName(rs.getString("name"));
dto.setAddr(rs.getString("addr"));
dto.setSdate(rs.getTimestamp("sdate"));
list.add(dto);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.dbClose(rs, pstmt, conn);
}
return list;
}
- DB에 insert, delete 받은 전체 데이터를 유동적 크기로 저장하기 위해 List 객체 사용(List는 인터페이스이므로 하위 클래스인 Vector 사용)
- 클래스의 반환 값이 Vector이며 제네릭 값으로 DTO 클래스(이곳의 멤버 변수를 사용하기 위해) 설정
- PrepareStatement와 ResultSet 객체를 이용해 sql 명령문을 전달 후 실행 및 데이터 가져옴
- ResultSet 객체의 getString() 메서드를 이용해 각 컬럼의 데이터 값을 문자열로 호출(date 타입의 sdate는 getTimestamp() 메서드 이용)
- 문자열로 호출 받은 값을 DTO의 setter를 통해 멤버 변수의 값을 변경
- List(Vector 클래스)의 add() 메서드를 통해 DTO에 변경한 멤버 변수를 저장 후 이를 반환
public void deleteSinsang(String num) {
Connection conn=db.getConnection();
PreparedStatement pstmt=null;
String sql="delete from sinsang where num=?";
try {
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, num);
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
db.dbClose(pstmt, conn);
}
}
- DB의 데이터를 삭제하기 위한 메서드
- 메서드의 인자 값으로 받아온 num 값을 PreparedStatement 객체를 이용해 sql 명령문에 입력 후 execute() 혹은 executeUpdate() 메서드를 통해 Oracle에서 실행
<body>
<form action="insertAction.jsp" method="post">
<table>
<tr>
<th>이름</th>
<td>
<input type="text" name="name" placeholder="이름입력" required="required">
</td>
</tr>
<tr>
<th>주소</th>
<td>
<input type="text" name="addr" placeholder="주소입력" required="required">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="전송">
<input type="button" value="목록" onclick="location.href='list.jsp'">
</td>
</tr>
</table>
</form>
</body>
- insert에 필요한 2가지 컬럼 값(name, addr)을 입력하기 위한 text 타입의 툴과 이를 DB에 전송할 submit 타입의 <input> 버튼 생성
- 입력 받은 데이터를 전송하기 위해 전체 태그를 감싸는 <form>태그
- <form>에서, 보안이 필요한 정보이므로 method는 post로 설정하며, 데이터를 전송하여 처리할 파일의 경로를 action 속성의 url로 작성
Insert Action(jsp)
- <form>에서 전달 받은 insert 요청을 처리하기 위한 메서드
<%
String name=request.getParameter("name");
String addr=request.getParameter("addr");
//입력데이터를 dto로 묶어서
SinsangDto dto=new SinsangDto();
dto.setName(name);
dto.setAddr(addr);
//insert메서드 전달
SinsangDao dao=new SinsangDao();
dao.insertSinsang(dto);
//출력 jsp로 이동..url이 바뀜
response.sendRedirect("list.jsp");
%>
- DAO(SinsangDao)에서 <form>의 action 속성으로 넘겨준 입력 데이터를 request.getParameter() 함수로 받아옴
- 이를 DTO의 멤버 변수에 대입하기 위해 setter, getter 메서드 사용(이를 위해 DTO 클래스 생성)
- DTO의 전체 멤버 변수를 포함하는 DTO 클래스 자체를 insertSinsang() 메서드에 인자 값으로 보내줌(이를 위해 DAO 클래스 생성)
- response 객체 : 웹 브라우저의 요청에 응답하는 것을 response라고 하며, 이러한 응답의 정보를 가지고 있는 객체가 response객체
- sendRedirect(url) 객체 : 지정한 url로 이동하게 하는 객체
- 즉 response.sendRedirect()는 웹브라우저에서 입력 값을 전송 받으면 이에 대한 응답으로 지정한 url(list.jsp)로 이동하게 하는 객체
- 요컨대 <form>에서 값을 입력 받아 이를 Vector 리스트에 저장 후 list.jsp 파일로 이동
Print List(jsp)
<%@page import="model.sinsang.SinsangDto"%>
<%@page import="java.util.Vector"%>
<%@page import="model.sinsang.SinsangDao"%>
<%
SinsangDao dao=new SinsangDao();
Vector<SinsangDto> list=dao.getAllDatas();
%>
- DAO의 getAllDatas() 메서드를 통해 저장된 모든 데이터를 호출
<body>
<button type="button" onclick="location.href='insertForm.jsp'">데이터추가</button>
<br>
<table>
<tr>
<th>번호</th>
<th>이름</th>
<th>주소</th>
<th>날짜</th>
<th>편집</th>
</tr>
<%
for(int i=0;i<list.size();i++)
{
SinsangDto dto=list.get(i);
%>
<tr>
<td><%=i+1 %></td>
<td><%=dto.getName() %></td>
<td><%=dto.getAddr() %></td>
<td><%=dto.getSdate() %></td>
<button type="button"
onclick="location.href='delete.jsp?num=<%=dto.getNum()%>'">삭제</button></td>
</tr>
<%}
%>
</table>
</body>
- <form>에서 데이터를 입력하면 이를 Vector 리스트에 저장 후 본 파일로 이동
- onclick 속성에서 지정한 url로 이동하는 속성 값은 location.href=’url’
- 다시 데이터를 입력하기 위해서 Form 파일(insertForm)로 이동하는 버튼 생성
- size() : List 인터페이스 및 하위 클래스의 원소 갯수를 호출하는 메서드
- get() : 인자의 인덱스 값에 해당하는 List의 원소 값을 호출하는 메서드
- List(Vector<SinsangDto>)에 저장된 각 원소 데이터(DTO의 멤버 변수 전체)를 DTO의 getter를 통해 <td>에 호출
- 삭제 버튼 클릭 시 delete.jsp 파일로 이동하며 인자 값으로 DTO의 num 변수 값을 입력(? 이후의 값을 인자 값으로 넘겨줌)
Delete Action(jsp)
<body>
<%
//삭제메서드 호출
String num=request.getParameter("num");
SinsangDao dao=new SinsangDao();
dao.deleteSinsang(num);
//리스트로 이동
response.sendRedirect("list.jsp");
%>
</body>
- Print List에서 인자 값으로 받아온 num의 변수 값을 request.getParameter() 객체로 호출
- DAO의 deleteSinsang() 메서드를 통해 Oracle DB에 delete 명령문을 전달 및 실행
- respose.sendRedirect() 객체를 통해 DB 데이터 삭제를 완료 후 list.jsp로 재이동
- DB 데이터가 삭제되면 Vector<SinsangDto> 값과 size가 변하므로 list.jsp의 <table>에 출력되는 값도 변경