JSP & Servlet-8日目(MySQLとの連携)

JSP&Servlet

いよいよMySQLと連携させて、標準的なCRUDアプリを作成してみよう。
[実行例]
●スタート画面

●フォームに入力する

●登録ボタンを押すと、登録しましたというメッセージが表示されるとともに下部にリストアップ。

●同様の作業を繰り返し3件ほど登録する。

●更新ボタンを押すとその情報がフォームに表示され、編集モードとなる(図はpro3の更新を押した)

●値段を8000円に変更して、更新ボタンを押した。

●削除を押すと確認のダイアログ(今回はpro1の削除ボタンを押した)

●okを押すと項目が削除される。

作成

1.MySQLでデータベース[product]を作成する。

CREATE DATABASE product 
DEFAULT CHARACTER SET utf8;

2.データベースproductに[products]テーブルを作成する。

CREATE TABLE products( 
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL, 
  price INT, 
  updated DATETIME 
);

3.https://dev.mysql.com/downloads/connector/j/にアクセスして、MySQLのJDBCをダウンロードする。(バージョンは5.1.47推奨2021年追記)

遷移したら「No thanks, just start my download.」をクリック

4.エクリプス。新規動的Webプロジェクトを選択し「joytas8」を作成する。
5.WEB-INFフォルダにあるlibフォルダに先程ダウンロードしたJDBCをコピペで貼り付ける。

6.context.xmlを以下のように編集。

<?xml version="1.0" encoding="UTF-8" ?>
<Context>
  <Resource
      name="jdbc/jsp"
      auth="Container"
      type="javax.sql.DataSource"
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost:3306/product"
      connectionProperties="autoReconnect=true;verifyServerCertificate=false;useSSL=false;requireSSL=false;useUnicode=true;characterEncoding=UTF-8;"
      username="root"
      validationQuery="select 1"/>
 </Context>

上はrootユーザー、パスワードなしが前提だが、ユーザー、パスワードを設定している場合は以下

<?xml version="1.0" encoding="UTF-8" ?>
<Context>
  <Resource
      name="jdbc/jsp"
      auth="Container"
      type="javax.sql.DataSource"
      driverClassName="com.mysql.jdbc.Driver"
      url="jdbc:mysql://localhost:3306/product"
      connectionProperties="autoReconnect=true;verifyServerCertificate=false;useSSL=false;requireSSL=false;useUnicode=true;characterEncoding=UTF-8;"
      username="root"
      password="root"
      validationQuery="select 1"/>
 </Context>

7.作成したcontext.xmlをMETA-INFの直下に配置

8.modelの作成。modelパッケージにProductクラスを以下のように作成
●model.Product.java

package model;
import java.io.Serializable;

public class Product implements Serializable{
	private int id;
	private String name;
	private int price;
	private String updated;
	public Product(){}
	public Product(String name,int price,String updated){
		this.name=name;
		this.price=price;
		this.updated=updated;
	}
	public Product(int id,String name,int price,String updated){
		this(name,price,updated);
		this.id=id;

	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public String getUpdated() {
		return updated;
	}
	public void setUpdated(String updated) {
		this.updated = updated;
	}	

}

9.DAOの作成。daoパッケージを作成し、その中にProductDAO.javaを作成する。
●dao.ProductDAO.java

package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import model.Product;

public class ProductDAO {
	private Connection db;
	private PreparedStatement ps;
	private ResultSet rs;

private void getConnection() throws NamingException, SQLException{
			Context context=new InitialContext();
			DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/jsp");
			this.db=ds.getConnection();
	}
	private void disconnect(){
		try{
			if(rs != null){rs.close();}
			if(ps != null){ps.close();}
			if(db != null){db.close();}
		}catch(SQLException e){
			e.printStackTrace();
		}
	}
	public List<Product> findAll(){

		List<Product> productList=new ArrayList<>();
		try {
			this.getConnection();
			ps=db.prepareStatement("SELECT * FROM products ORDER BY id DESC");
			rs=ps.executeQuery();
			while(rs.next()){
				int id=rs.getInt("id");
				String name=rs.getString("name");
				int price=rs.getInt("price");
				SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				String updated=sdf.format(rs.getTimestamp("updated"));
				Product product=new Product(id,name,price,updated);
				productList.add(product);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (NamingException e) {
			e.printStackTrace();
		}finally{
			this.disconnect();
		}
		return productList;
	}
	public boolean insertOne(Product product){
		try {
			this.getConnection();
			ps=db.prepareStatement("INSERT INTO products(name,price,updated) VALUES(?,?,?)");
			ps.setString(1,product.getName());
			ps.setInt(2,product.getPrice());
			ps.setString(3, product.getUpdated());
			int result=ps.executeUpdate();
			if(result != 1){
				return false;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (NamingException e) {
			e.printStackTrace();
		}finally{
			this.disconnect();
		}
		return true;
	}
	public Product findOne(int id){
		Product product=null;
		try{
			this.getConnection();
			ps=db.prepareStatement("SELECT * FROM products WHERE id=?");
			ps.setInt(1, id);
			rs=ps.executeQuery();
			if(rs.next()){
				String name=rs.getString("name");
				int price=rs.getInt("price");
				String updated=rs.getString("updated");
				product=new Product(id,name,price,updated);
			}

		}catch (SQLException e) {
			e.printStackTrace();
		} catch (NamingException e) {
			e.printStackTrace();
		}finally{
			this.disconnect();
		}
		return product;
	}
	public boolean updateOne(Product product){
		try{
			this.getConnection();
			ps=db.prepareStatement("UPDATE products SET name=?,price=?,updated=? WHERE id=?");
			ps.setString(1, product.getName());
			ps.setInt(2, product.getPrice());
			ps.setString(3, product.getUpdated());
			ps.setInt(4, product.getId());
			int result=ps.executeUpdate();
			if(result != 1){
				return false;
			}
		}catch (SQLException e) {
			e.printStackTrace();
		} catch (NamingException e) {
			e.printStackTrace();
		}finally{
			this.disconnect();
		}
		return true;
	}
	public boolean deleteOne(int id){

		try{
			this.getConnection();
			ps=db.prepareStatement("DELETE FROM products WHERE id=?");
			ps.setInt(1, id);
			int result=ps.executeUpdate();
			if(result != 1){
				return false;
			}
		}catch (SQLException e) {
			e.printStackTrace();
		} catch (NamingException e) {
			e.printStackTrace();
		}finally{
			this.disconnect();
		}
		return true;
	}

}

10.viewの作成。以下の図のようなフォルダ構成としmain.jspを作成する。

●main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="model.*,java.util.*"%>
<%
	List<Product> list=(List<Product>)request.getAttribute("list");
	Product product=(Product)request.getAttribute("product");
	String id=product==null ? "":String.valueOf(product.getId());
	String name=product == null ? "":product.getName();
	String price=product == null ? "":String.valueOf(product.getPrice());
	String title=(String)request.getAttribute("title");
	title=title==null? "商品を登録してください。":title;
	String err=(String)request.getAttribute("err");
	String msg=(String)request.getAttribute("msg");

%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<title>Joytas8</title>
</head>
<body>
<div class="container" style="margin-top:20px;">
<% if(err !=null){%>
<div class="alert alert-danger" role="alert">
<%=err %>
</div>
<%} %>
<% if(msg !=null){%>
<div class="alert alert-success" role="alert">
<%=msg %>
</div>
<%} %>
<p><%=title %></p>

<form action="/joytas8/main" method="post" >
  <div class="form-group">
    <label for="name">製品名:</label>
    <input type="text" id="name" name="name" class="form-control" style="width:200px;" value="<%=name%>">
  </div>
  <div class="form-group">
    <label for="price">価格:</label>
    <input type="number" id="price" name="price" class="form-control" style="width:200px;" value="<%=price%>">
  </div>
  <%if(!id.isEmpty()) {%>
  <input type="hidden" name="id" value="<%=id %>">
  <%} %>
  <button type="submit" class="btn btn-primary"><%=id.isEmpty()?"登録":"更新" %></button>
</form>

<%if(list != null && list.size()>0){%>
<table class="table table-striped mt-4">
<tr><th>製品名</th><th>価格</th><th>更新日</th><th></th></tr>
<%for(Product p:list) {%>
<tr><th><%=p.getName() %></th><td><%=String.format("%,3d円",p.getPrice()) %></td><td><%=p.getUpdated() %></td>
<td>
<a href="/joytas8/main?action=update&id=<%=String.valueOf(p.getId()) %>" class="btn btn-primary">更新</a>
<a href="/joytas8/main?action=delete&id=<%=String.valueOf(p.getId()) %>" class="btn btn-danger" onclick="return confirm('削除してよろしいですか?');">削除</a>
</td>
</tr>
<%} %>
</table>
<%} %>
</div>
<script>
const forms=document.getElementsByClassName("form-control");
const alerts=document.getElementsByClassName("alert");
for(let i=0;i<forms.length;i++){
	forms[i].addEventListener("focus",()=>{
		for(let j=0;j<alerts.length;j++){
			alerts[j].style.display="none";
		}
	});
}
</script>
</body>
</html>

11.controllerの作成。以下のようなフォルダ構成とし、Main.java(Servlet)を作成する。

●controller.Main.java

package controller;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import dao.ProductDAO;
import model.Product;

@WebServlet("/main")
public class Main extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ProductDAO dao=new ProductDAO();
		String action=request.getParameter("action");
		if(action != null && action.equals("delete")){
			dao.deleteOne(Integer.parseInt(request.getParameter("id")));
			request.setAttribute("msg", "1件削除しました。");
		}else if(action != null && action.equals("update")){
			Product product=dao.findOne(Integer.parseInt(request.getParameter("id")));
			request.setAttribute("product", product);
			request.setAttribute("title", "項目を編集してください。");
		}
		List<Product> list=dao.findAll();
		request.setAttribute("list", list);
		RequestDispatcher rd= request.getRequestDispatcher("/WEB-INF/view/main.jsp");
		rd.forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String name=request.getParameter("name");
		String price=request.getParameter("price");
		if(name.isEmpty() || price.isEmpty()){
			request.setAttribute("err","未記入の項目があります!");
		}else{
			Date date=new Date();
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String updated=sdf.format(date);
			ProductDAO dao=new ProductDAO();
			String id=request.getParameter("id");
			if(id != null){
				dao.updateOne(new Product(Integer.parseInt(id),name,Integer.parseInt(price),updated));
				request.setAttribute("msg","1件更新しました。");
			}else{
				dao.insertOne(new Product(name,Integer.parseInt(price),updated));
				request.setAttribute("msg","1件登録しました。");
			}
		}
		doGet(request,response);
	}
}

12.サーバーで実行後以下のアドレスにリクエストして、実行例のようになることを確認する。
http://localhost:8080/joytas8/main

コメント

タイトルとURLをコピーしました