치킨에 대한 리뷰를 작성하는 기능
CREATE TABLE review(
code number,
name varchar(100),
grade int,
text varchar(100),
rev_num NUMBER GENERATED ALWAYS AS IDENTITY,
CONSTRAINT rev_pri PRIMARY KEY(code,rev_num),
foreign key (code) references chicken(code),
CONSTRAINT cons_grade CHECK (grade>0 AND grade <=5)
);
<review.sql>
review table을 생성하여 DB에 저장될 수 있도록 하였다.
각 리뷰를 구분하기 위해서 치킨의 코드와 자동생성된 rev_num 속성을 기본키로 지정하였고 치킨 테이블의 코드를 외래키로 만들었다.
평점은 0과 5사이의 값을 가지도록 제약조건을 명시하였다.
package dao;
import static com.smc.db.JdbcUtil.*;
import java.util.ArrayList;
import java.sql.*;
import org.springframework.stereotype.Repository;
import vo.Chicken;
import vo.Review;
@Repository
public class RevDAO {
Connection con;
private static RevDAO rDAO;
public void setConnection(Connection con) { this.con = con;}
public static RevDAO getInstance() {
if(rDAO==null) rDAO = new RevDAO();
return rDAO;
}
public int insertReview(Review rev) {
PreparedStatement pstmt = null;
PreparedStatement pstmt2 = null;
int insertCount = 0;
String Sql = "";
String Sql2 = "update review set code = (select code from chicken where review.name = chicken.name)";
try {
Sql = "insert into review(code,name,grade,text) values(?,?,?,?)";
pstmt = con.prepareStatement(Sql);
pstmt.setInt(1,1);
pstmt.setString(2, rev.getName());
pstmt.setInt(3,rev.getGrade());
pstmt.setString(4, rev.getText());
insertCount = pstmt.executeUpdate();
pstmt2 = con.prepareStatement(Sql2);
insertCount+=pstmt2.executeUpdate();
}catch(SQLIntegrityConstraintViolationException e){
System.out.println("이미 같은 정보가 있습니다.");
return -1;
}catch(SQLException e) {
e.printStackTrace();
}finally { close(pstmt); close(pstmt2);}
return insertCount;
}
public ArrayList<Review> getReviewList(){
PreparedStatement pstmt = null;
ResultSet rs = null;
ArrayList<Review> Rlist = null;
try {
pstmt = con.prepareStatement("SELECT * FROM review");
rs = pstmt.executeQuery();
if(rs.next()) {
Rlist = new ArrayList<>();
do {
Rlist.add(new Review(rs.getString("name"),rs.getInt("grade"),rs.getString("text")));
} while(rs.next());
}
} catch(SQLException e) {
e.printStackTrace();
}finally {close(rs); close(pstmt);}
return Rlist;
}
}
<ReviewDAO.java>
DB connection을 DAO 객체에 할당할 수 있는 setConnection 함수와 static 함수로서 객체를 반환하는 getinstance함수, 그리고 리뷰를 DB에 작성할 수 있는 insertReview 함수를 작성하였다.
일단 code값은 preparedstatement 객체에 임의로 지정한 값을 삽입하고, 나머지는 입력받은 값을 삽입한다.
그리고 update문을 이용하여 리뷰가 작성된 치킨의 이름을 chicken table에 들어가 있는 치킨 중에서 찾고, 해당 치킨의 code 값을 review table의 code값에 매핑시킨다.
치킨 등록과 마찬가지로 SQLIntegrityConstraintViolationException(무결성 제약조건 위배)의 경우는 따로 예외처리를 하고 return 값을 다르게 하여 구분할 수 있도록 하였다.
package service;
import static com.smc.db.JdbcUtil.*;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import vo.Review;
import dao.RevDAO;
@Service
public class ReviewInsertService {
public RevDAO rDAO = new RevDAO();
public int insertRev(Review rev) {
rDAO = RevDAO.getInstance();
Connection con = getConnection();
rDAO.setConnection(con);
int cnt = rDAO.insertReview(rev);
int isSuccess = 0;
if(cnt>0) {commit(con); isSuccess = 1;}
else if(cnt==-1) {return -1;}
else rollback(con);
close(con);
return isSuccess;
}
}
<ReviewInsertService.java>
DAO 객체를 생성하고 DB Connection을 할당한 후 매개변수로 받은 review를 DB에 삽입하는 insertRev 함수를 작성하였다.
package com.smc.test;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class ReviewInsertController {
@RequestMapping(value = "/CReview.chic" , method = RequestMethod.GET)
public String view(HttpServletRequest request ,Model model) {
String result = "CReview";
return result;
}
}
<ReviewInsertController.java>
삽입할 review 객체 생성 후 view에서 처리하는 것이 편할 것 같아서 Controller에는 다른 코드를 작성하지 않았다.
MVC 패턴이 이게 맞는 건지 의문이 들지만 다음 프로젝트에서 좀 더 공부해서 발전된 코드를 작성할 수 있도록 해야겠다.
<%@ page import = "vo.Review" %>
<%@ page import = "service.ReviewInsertService" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP Title</title>
</head>
<body>
<header>
<img src = "resources/img/SMClogo.png" width = "50" height = "50">
<a href = "/test"><img src = "resources/img/logo2.png" width = "140" height = "50"></a>
<a href= "CList.chic"><img src = "resources/img/list.png" width = "120" height = "50"></a>
<a href= "CInsert.chic"><img src = "resources/img/regist.png" width = "120" height = "50"></a>
</header>
<%
String name = request.getParameter("name");
%>
<form class = "Rev-regist" action = "/test/CReview.chic" method = "get">
<h3><%=name %> 리뷰 쓰기</h3>
이름 : <input type = "text" name = "name" value ="<%=name %>" readonly>
평점 : <input type="number" min="0" max="5" step = 1 name ="grade" required = "required"><br>
리뷰 : <textarea name = "text" cols="50" rows="10"></textarea>
<%
name = request.getParameter("name");
String grade = request.getParameter("grade");
String review = request.getParameter("text");
if(grade!=null&&name!=null){
Review rev = new Review(name,Integer.parseInt(grade),review);
ReviewInsertService ris = new ReviewInsertService();
int iS = ris.insertRev(rev);
if(iS==1) out.println("등록 완료되었습니다.");
else if(iS==-1){out.println("등록 과정에서 오류가 발생했습니다.");}
else out.println("등록에 실패하였습니다.");
}
%>
<button class = "btn" type = "submit">등록</button>
</form>
<form class = "Rev-list" action = "/test/Rlist.chic" method = "get">
<input type = "hidden" name = "name" value ="<%=name %>" >
<button class = "btn" type = "submit">리뷰 목록으로</button>
</form>
</body>
</html>
<CReview.jsp>
치킨 리스트에서 get 형식으로 보낸 name을 getParameter 함수를 이용해 받고 평점, 리뷰 값과 함께 저장한 뒤 해당 값으로 review 객체를 만들고 ReviewInsertService 객체를 이용해서 DB에 삽입하는 코드이다.
SQLIntegrityConstraintViolationException가 발생할 경우 -1를 return 하기 때문에 따로 처리하여 확인할 수 있도록 작성했다.