지금까지 ArrayList
에 저장하던 상품 목록을 데이터베이스에 저장하고, 데이터베이스를 JSP와 연동해 상품 목록을 가져오도록 수정한다.
데이터베이스를 관리하기 위해 MySQL
을 사용하고 데이터베이스와 JSP를 연동하기 위해 JDBC
를 사용한다.
JDBC란? 자바에서 데이터베이스 작업을 처리할 수 있게 하는 자바 라이브러리
MySQL
설치 후 MySQL workbench
에서 데이터베이스, 상품 테이블을 생성하는 SQL문 작성
(SQL은 추후 더 자세히 배울 예정)
// webmarketdb 데이터베이스 생성
CREATE database webmarketdb default character set utf8 collate utf8_general_ci;
// 사용할 데이터베이스 지정
USE WebMarketDB;
// product 테이블 생성, 기본 키 p_id
CREATE TABLE IF NOT EXISTS product(
p_id VARCHAR(10) NOT NULL,
p_name VARCHAR(20),
p_unitPrice INTEGER,
p_description TEXT,
p_category VARCHAR(20),
p_manufacturer VARCHAR(20),
p_unitsInStock LONG,
p_condition VARCHAR(20),
p_fileName VARCHAR(20),
PRIMARY KEY (p_id)
)default CHARSET=utf8;
// 테이블에 상품 추가하기
INSERT INTO product VALUES('P1234', 'iPhone 6s', 800000, '1334X750 Renina HD display, 8-megapixel iSight Camera','Smart Phone', 'Apple', 1000, 'new', 'p1234.jpg');
INSERT INTO product VALUES('P1235', 'LG PC gram', 1500000, '3.3-inch,IPS LED display, 5rd Generation Intel Core processors', 'Notebook', 'LG', 1000, 'new', 'p1235.jpg');
INSERT INTO product VALUES('P1236', 'Galaxy Tab S', 900000, '3.3-inch, 212.8*125.6*6.6mm, Super AMOLED display, Octa-Core processor', 'Tablet', 'Samsung', 1000, 'new', 'p1236.jpg');
mysql-connector-java-8.0.29.jar
라이브러리를 lib 폴더에 저장하고 자바와 데이터베이스를 연결하는 페이지 작성
데이터베이스 연결이 필요한 페이지에서 해당 파일을 include
파일명 : dbconn.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<%
// DB와 jsp를 연결하는 객체
Connection conn = null;
String url = "jdbc:mysql://localhost:3306/WebMarketDB";
String user = "root";
String password = "1234";
try {
// 드라이버 파일 로드해오기
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
} catch(SQLException e) {
out.println("데이터베이스 연결에 실패했습니다.<br>");
out.println("SQLException : "+e.getMessage());
}
%>
상품 목록을 데이터베이스에서 가져와 출력하도록 코드 수정
파일명 : products.jsp
...
<%@ page import="java.sql.*" %>
<!-- DB 연결이 필요한 페이지에 include -->
<%@ include file="dbconn.jsp" %>
...
<div class="container">
<div class="row" align="center">
<!-- SQL 사용해 DB에서 상품 정보 가져오기 -->
<%
// 데이터베이스에 SQL문을 전달하는 PreparedStatement 객체
PreparedStatement pstmt = null;
// 데이터베이스로부터 결과값을 전달받는 ResultSet 객체
ResultSet rs = null;
// SQL문 작성하고 실행하기
String sql = "select * from product";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
// 실행한 결과값 rs(product 테이블의 모든 레코드) 하나씩 출력
while (rs.next()) {
%>
<div class="col-md-4 p-4">
<img src="./resources/images/<%= rs.getString("p_fileName") %>" style="width:100%;">
<h3><%= rs.getString("p_name") %></h3>
<p><%= rs.getString("p_description") %></p>
<p><%= rs.getString("p_UnitPrice") %>원</p>
<p><a href="./product.jsp?id=<%= rs.getString("p_id") %>" class="btn btn-secondary" role="button">상세 정보 »</a></p>
</div>
<%
}
%>
</div>
...
새로 추가하는 상품이 데이터베이스에 등록되도록 코드 수정
파일명 : processAddProduct.jsp
<%@ page import="java.sql.*" %>
<%@ include file="dbconn.jsp" %>
...
// SQL 사용해 DB에 상품 등록하기
PreparedStatement pstmt = null;
String sql = "insert into product values(?,?,?,?,?,?,?,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, productId);
pstmt.setString(2, name);
pstmt.setInt(3, price);
pstmt.setString(4, description);
pstmt.setString(5, category);
pstmt.setString(6, manufacturer);
pstmt.setLong(7, stock);
pstmt.setString(8, condition);
pstmt.setString(9, productImage);
pstmt.executeUpdate();
if(pstmt != null) {
pstmt.close();
}
if(conn != null) {
conn.close();
}
// 상품 목록 페이지로 이동
response.sendRedirect("products.jsp");
%>
같은 페이지에서 edit
파라미터 값이 update
면 수정 버튼, delete
면 삭제 버튼이 나오도록 함
수정 버튼을 클릭하면 updateProduct.jsp
페이지로,
삭제 버튼을 클릭하면 deleteProduct.jsp
로 상품 id 가지고 이동
파일명 : editProduct.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 편집</title>
<script>
function deleteConfirm(id) {
if (confirm("해당 상품을 삭제합니다!!") == true) {
location.href = "./deleteProduct.jsp?id="+id;
} else {return;}
}
</script>
<link rel="stylesheet" href="./resources/css/bootstrap.min.css">
</head>
<%
String edit = request.getParameter("edit");
%>
<body>
<!-- menu -->
<jsp:include page="menu.jsp" />
<!-- jumbotron -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">상품 편집</h1>
</div>
</div>
<div class="container">
<div class="row" align="center">
<!-- DB 연결이 필요한 페이지에 include -->
<%@ include file="dbconn.jsp" %>
<!-- SQL 사용해 DB에서 상품 정보 가져오기 -->
<%
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "select * from product";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
%>
<div class="col-md-4 p-4">
<img src="./resources/images/<%= rs.getString("p_fileName") %>" style="width:100%;">
<h3><%= rs.getString("p_name") %></h3>
<p><%= rs.getString("p_description") %></p>
<p><%= rs.getString("p_UnitPrice") %>원</p>
<!-- 상품 아이디를 id 변수에 담아 파라미터로 전달 -->
<p>
<%
if(edit.equals("update")) {
%>
<a href="./updateProduct.jsp?id=<%= rs.getString("p_id") %>" class="btn btn-success" role="button">수정 »</a>
<%
} else if(edit.equals("delete")) {
%>
<a href="#" onclick="deleteConfirm('<%= rs.getString("p_id") %>')" class="btn btn-success" role="button">삭제 »</a>
<%
}
%>
</p>
</div>
<%
}
if (rs != null) { rs.close(); }
if (pstmt != null) { pstmt.close(); }
if (conn != null) { conn.close(); }
%>
</div>
<hr>
</div>
<!-- footer -->
<jsp:include page="footer.jsp" />
</body>
</html>
폼을 제출하면 processUpdateProduct.jsp
에서 처리
파일명 : updateProduct.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<%@ include file="dbconn.jsp" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>상품 수정</title>
<link rel="stylesheet" href="./resources/css/bootstrap.min.css">
</head>
<%
String edit = request.getParameter("edit");
%>
<body>
<!-- menu -->
<jsp:include page="menu.jsp" />
<!-- jumbotron -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">상품 수정</h1>
</div>
</div>
<%
String productId = request.getParameter("id");
PreparedStatement pstmt = null;
ResultSet rs = null;
// 데이터베이스에서 상품 id가 productId인 레코드 찾기
String sql = "select * from product where p_id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, productId);
rs = pstmt.executeQuery();
// 레코드가 존재하면 다음 내용 실행
if (rs.next()) {
%>
<div class="container">
<div class="row">
<div class="col-md-5">
<img src="./resources/images/<%= rs.getString("p_fileName") %>" style="width:100%;">
</div>
<div class="col-md-7">
<form name="newProduct" action="./processUpdateProduct.jsp" class="form-horizontal" method="post" enctype="multipart/form-data">
<div class="form-group row">
<label class="col-sm-2">상품 코드</label>
<div class="col-sm-3">
<input type="text" id="productId" name="productId" class="form-control" value='<%= rs.getString("p_id") %>'>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">상품명</label>
<div class="col-sm-3">
<input type="text" id="name" name="name" class="form-control" value='<%= rs.getString("p_name") %>'>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">가격</label>
<div class="col-sm-3">
<input type="text" id="unitPrice" name="unitPrice" class="form-control" value='<%= rs.getInt("p_unitPrice") %>'>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">상세 설명</label>
<div class="col-sm-5">
<textarea name="description" cols="50" rows="2" class="form-control"><%= rs.getString("p_description") %></textarea>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">제조사</label>
<div class="col-sm-3">
<input type="text" name="manufacturer" class="form-control" value='<%= rs.getString("p_manufacturer") %>'>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">분류</label>
<div class="col-sm-3">
<!-- 이미 선택된 category에 checked 되게 하는 방법? -->
<select name="category" class="custom-select">
<option value="Smart Phone">스마트폰</option>
<option value="Notebook">노트북</option>
<option value="Tablet">태블릿</option>
<option value="Others">기타</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">재고 수</label>
<div class="col-sm-3">
<input type="text" id="unitsInStock" name="unitsInStock" class="form-control" value='<%= rs.getLong("p_unitsInStock") %>'>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">상태</label>
<div class="col-sm-5">
<input type="radio" name="condition" value="New">
신규 제품
<input type="radio" name="condition" value="Old">
중고 제품
<input type="radio" name="condition" value="Refurbished">
재생 제품
</div>
</div>
<div class="form-group row">
<label class="col-sm-2">이미지</label>
<div class="col-sm-5">
<input type="file" name="productImage" class="form-control">
</div>
</div>
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" class="btn btn-primary" value="등록">
</div>
</div>
</form>
</div>
</div>
<hr>
</div>
<%
}
if (rs != null) { rs.close(); }
if (pstmt != null) { pstmt.close(); }
if (conn != null) { conn.close(); }
%>
<!-- footer -->
<jsp:include page="footer.jsp" />
</body>
</html>
전달받은 파라미터를 변수에 담고
상품 아이디로 수정할 상품 레코드를 데이터베이스에서 가져와
담은 변수를 set하고 해당 레코드를 update
파일명 : processUpdateProduct.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="com.oreilly.servlet.*" %>
<%@ page import="com.oreilly.servlet.multipart.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.sql.*" %>
<%@ include file="dbconn.jsp" %>
<%
// 파일을 전달받기 위한 작업
String path = "./resources/images";
String savedir = request.getServletContext().getRealPath(path);
int maxSize = 5*1024*1024;
String encType = "utf-8";
// 전달값 접근을 위한 MultipartRequest 객체 생성
MultipartRequest multi = new MultipartRequest(request, savedir, maxSize, encType);
// 전달받은 파라미터 담기
String productId = multi.getParameter("productId");
String name = multi.getParameter("name");
String unitPrice = multi.getParameter("unitPrice");
String description = multi.getParameter("description");
String manufacturer = multi.getParameter("manufacturer");
String category = multi.getParameter("category");
String unitsInStock = multi.getParameter("unitsInStock");
String condition = multi.getParameter("condition");
// Product 객체에 set하기 위해 일부 값은 형변환 필요
Integer price;
if(unitPrice.isEmpty()) {
price = 0;
} else {
price = Integer.valueOf(unitPrice);
}
long stock;
if(unitsInStock.isEmpty()) {
stock = 0;
} else {
stock = Long.valueOf(unitsInStock);
}
// 이미지 파일 이름 가져오기
String productImage = multi.getFilesystemName("productImage");
PreparedStatement pstmt = null;
ResultSet rs = null;
// DB에서 수정할 상품 찾아 가져오기
String sql = "select * from product where p_id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, productId);
rs = pstmt.executeQuery();
if(rs.next()) {
// 업로드한 파일이 있으면
if (productImage != null) {
// p_id가 ~인 레코드의 내용 수정
sql = "UPDATE product SET p_name=?, p_unitPrice=?, p_description=?, p_manufacturer=?, p_category=?, p_unitsInStock=?, p_condition=?, p_fileName=? WHERE p_id=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setInt(2, price);
pstmt.setString(3, description);
pstmt.setString(4, manufacturer);
pstmt.setString(5, category);
pstmt.setLong(6, stock);
pstmt.setString(7, condition);
pstmt.setString(8, productImage);
pstmt.setString(9, productId);
pstmt.executeUpdate();
}
// 업로드한 파일이 없으면
else {
sql = "UPDATE product SET p_name=?, p_unitPrice=?, p_description=?, p_manufacturer=?, p_category=?, p_unitsInStock=?, p_condition=? WHERE p_id=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setInt(2, price);
pstmt.setString(3, description);
pstmt.setString(4, manufacturer);
pstmt.setString(5, category);
pstmt.setLong(6, stock);
pstmt.setString(7, condition);
pstmt.setString(8, productId);
pstmt.executeUpdate();
}
}
if (rs != null) { rs.close(); }
if (pstmt != null) { pstmt.close(); }
if (conn != null) { conn.close(); }
// 상품 수정 페이지로 이동
response.sendRedirect("editProduct.jsp?edit=update");
%>
파일명 : deleteProduct.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<%@ include file="dbconn.jsp" %>
<%
String productId = request.getParameter("id");
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "select * from product";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
if (rs.next()) {
// p_id가 ~인 레코드 삭제
sql = "delete from product where p_id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, productId);
pstmt.executeUpdate();
} else {
out.println("일치하는 상품이 없습니다.");
}
if (rs != null) { rs.close(); }
if (pstmt != null) { pstmt.close(); }
if (conn != null) { conn.close(); }
// 상품 삭제 페이지로 이동
response.sendRedirect("editProduct.jsp?edit=delete");
%>
상품 목록, 등록, 수정, 삭제 메뉴 추가
파일명 : menu.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<nav class="navbar navbar-expand navbar-dark bg-dark">
<div class="container">
<div class="navbar-header">
<a href="./welcome.jsp" class="navbar-brand">
Home
</a>
</div>
<div>
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a href="./products.jsp" class="nav-link">상품 목록</a>
</li>
<li class="nav-item">
<a href="./addProduct.jsp" class="nav-link">상품 등록</a>
</li>
<li class="nav-item">
<a href="./editProduct.jsp?edit=update" class="nav-link">상품 수정</a>
</li>
<li class="nav-item">
<a href="./editProduct.jsp?edit=delete" class="nav-link">상품 삭제</a>
</li>
</ul>
</div>
</div>
</nav>