Servletでデータベース

VsCodeでxamppのmariadbに接続するプログラムを開発

mariaDBの準備

xamppのMySQLはインストールすればたぶん安定して動きます。パスワードはなしのままで結構です。

現在のxamppは(2022/6/24現在)MySQLと表示されていますが、中身はmariaDBです。ただ扱いとしてはMySQLと同じで構いません。そしてJavaと接続するにはJDBCの機構を使ってつなぎますので、ドライバーが必要です。

MySQLとして接続もできますが、今回はmariaDBとして接続しましょう。

mariaDB driverで検索すると

mariaDB search

と出てきたらクリックして、mariaDBのサイトにたどり着きましょう。英語かもしれません。

mariaDB site

DOWNLOADをクリックして、ダウンロードページに行ってください。

mariaDB download

少し下の方で、バージョンを選ぶ場所がありますので、これを操作して自分の環境に合わせます。

mariaDB download

私は Java17ですので、+8の 3.0.5を選びました。下にDOWNLOADボタンがあるので、これでjarファイルをダウンロードします。

このjarファイルをコンパイルと実行時に使います。まずは実行時に備えて、xamppのtomcatのlibにコピーします。

tomcat lib

こうしておけばTOMCATで実行時にここのlibが自動的に使われるのでエラーが発生しません。

データベースの準備

今回のアプリで使うデータベースを宣言しておきましょう

MemoDataというテーブルを aid int(11) NOT NULL,smemo text NOT NULL,stime datetime NOT NULL,sst int(11) NOT NULL,scategory varchar(30) DEFAULT NULL で作ります。

memodata

備忘録を保存するアプリとして使います。

まず、mariaDBと接続できるかのテストのために一度仮のプログラムを作って実験してみましょう。

src/main/java/jp/co/etlab/Main.java
	package jp.co.etlab;

	import java.io.IOException;
	import java.util.Date;
	import java.sql.Connection;
	import java.sql.DriverManager;
	import java.sql.PreparedStatement;
	import java.sql.SQLException;
	
	import javax.servlet.ServletException;
	import javax.servlet.annotation.WebServlet;
	import javax.servlet.http.HttpServlet;
	import javax.servlet.http.HttpServletRequest;
	import javax.servlet.http.HttpServletResponse;
	
	@WebServlet("/Main")
	public class Main extends HttpServlet {
		private static final long serialVersionUID = 1L;
	
		protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
			Connection con = null;
			try {
				Class.forName("org.mariadb.jdbc.Driver");
			} catch (ClassNotFoundException e) {
				//	throw new IllegalStateException("ドライバーのロードに失敗しました");
				//無視する
			}
			try {
				con = DriverManager.getConnection("jdbc:mariadb://localhost:3306/mydb","root","");
	
				//step2 送信すべきSQL文のひな形を準備
				PreparedStatement pstmt  = con.prepareStatement
					("INSERT INTO MEMODATA (SMEMO,STIME,SST,SCATEGORY) VALUES (?,?,?,?)");
				//ひな形に値を流し込む
				Date d = new Date();
				long l = d.getTime();
				java.sql.Timestamp ts = new java.sql.Timestamp(l);
	
				pstmt.setString(1,"日本語が登録できるか");
				pstmt.setTimestamp(2,ts);
				pstmt.setInt(3, 1);	//1=waitStart
				pstmt.setString(4, "#java #database #mariadb");
				//DBMSに検索系を送信
				int r = pstmt.executeUpdate();
				//処理結果を見る
				if (r==1) {
					System.out.println("SUCCSESS");
				} else {
					System.out.println("ERROR");
				}
				pstmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			} finally {
				if (con != null) {
					try {
						con.close();
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

この中でやっているのは、mariadbのドライバーのロード。ただし、この環境でやるとかならず1回目の起動でロードエラーになるので、catchはやめてあります。

ロードできたら、今回使ったmariaDBのmydbデータベースに接続します。3306ポートがmariaDBのポート番号、MySQLと同じです。ここのところをMySQLでやりたいのであれば、MySQLのドライバーをダウンロードしてjdbc:mysqlに接続してください。どちらでもつながります。

そして、SQL文を作成し、プリペアードステートメントで埋めていきます。日付時刻は面倒くさいことになってます。一度longに変換してから変換です。

成功すれば成功したレコード数が返ってくるので1ならば成功、それ以外は失敗です。これが正しく動くことを確認してからでないと次に進めませんので、ちゃんと実行してください。実行方法は前回の回と同じでMAVENをinstall,compile,packageしてTOMCATで実験してください。

最初の実行で localhost:8080/vsdbaccess でHello, worldが表示されますが、それはデファルトのindex.jspですので関係ありません。その後に /Main を追加して実行すると、出力に SUCCESSと表示されれば成功です。

success

うまくいっていれば、テストデータがmydbのmemodataテーブルに入っているはずです。確認してください。

memodata

MVCモデルを作ってみる

さきほどのMain.javaのように毎回データベースへの接続を書いていると同じようなプログラムが乱立してしまい、見通しがよくありません。そこでMVCモデルという構造を作って、Mでやり取りの構造体や処理、Vで画面の表示、Cが全体のコントロールという風に作っていってみましょう。

概要図

Main.javaが最初にパラメータなしのGetを受けて、AraryListにデータベースを詰め込んでjspをPOSTする。JSPのFormからデータがPOSTされればInsertし、またListを返し、DeleteがGETされればDeleteしてListを返すを繰り返します。

まず、このMemoDataのクラスを作って、データベースとのやり取りのひな形を作ります。このようなやり方をJavaBeansといいます。

etlabのフォルダーにmodelフォルダーを作り、その中にMemoData.javaを作ります。

src/main/java/jp/co/etlab/model/MemoData.java
	package jp.co.etlab.model;

	import java.io.Serializable;
	import java.util.Date;
	
	public class MemoData implements Serializable{
		private int aid;
		private String smemo;
		private Date stime;
		private int sst;
		private String scategory;
	
		public MemoData() {}
		public MemoData(String smemo, String scategory) {
			this.smemo = smemo;
			this.scategory = scategory;
		}
		public MemoData(int aid, String smemo, Date stime, int sst, String scategory) {
			this.aid = aid;
			this.smemo = smemo;
			this.stime = stime;
			this.sst = sst;
			this.scategory = scategory;
		}
		public int getAid() {
			return aid;
		}
		public void setAid(int aid) {
			this.aid = aid;
		}
		public String getSmemo() {
			return smemo;
		}
		public void setSmemo(String smemo) {
			this.smemo = smemo;
		}
		public Date getStime() {
			return stime;
		}
		public void setStime(Date stime) {
			this.stime = stime;
		}
		public int getSst() {
			return sst;
		}
		public void setSst(int sst) {
			this.sst = sst;
		}
		public String getScategory() {
			return scategory;
		}
		public void setScategory(String scategory) {
			this.scategory = scategory;
		}
	}

このクラスがデータベースや各メソッドでのデータのやり取りの入れ物になります。

続いて、やり取りの処理ロジックを代行してくれるメソッドを作ります。

etlabフォルダーの中に、daoフォルダーを作りInsertDAO.javaを作成します。実はこの中身は先ほど作った仮のMain.javaとほぼ同じです。中身をコピーしてきて修正してください。

src/main/java/jp/co/etlab/dao/InsertDAO.java
	package jp.co.etlab.dao;

	import java.sql.Connection;
	import java.sql.DriverManager;
	import java.sql.PreparedStatement;
	import java.sql.SQLException;
	import java.util.Date;
	
	import jp.co.etlab.model.MemoData;
	
	public class InsertDAO {
		public static boolean insertData(MemoData md ) throws ClassNotFoundException{
			Connection con = null;
			try {
				Class.forName("org.mariadb.jdbc.Driver");
			} catch(ClassNotFoundException e) {
				//
			}
	
			try {
				con = DriverManager.getConnection("jdbc:mariadb://localhost:3306/mydb","root","");
				//step2 送信すべきSQL文のひな形を準備
				PreparedStatement pstmt  = con.prepareStatement
					("INSERT INTO MEMODATA (SMEMO,STIME,SST,SCATEGORY) VALUES (?,?,?,?)");
				//ひな形に値を流し込む
				Date d = new Date();
				long l = d.getTime();
				java.sql.Timestamp ts = new java.sql.Timestamp(l);
	
				pstmt.setString(1,md.getSmemo());
				pstmt.setTimestamp(2,ts);
				pstmt.setInt(3, 1);	//1=waitStart
				pstmt.setString(4, md.getScategory());
				//DBMSに検索系を送信
				int r = pstmt.executeUpdate();
				//処理結果を見る
				pstmt.close();
	
				if (r==1) {
					return true;
				} else {
					return false;
				}
			} catch (SQLException e) {
				e.printStackTrace();
				return false;
			} finally {
				if (con != null) {
					try {
						con.close();
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

このDAOが、データベースとのやり取りをやってくれるので、これさえあればデータベースのことをこのDAO以外では気にしないで、modelのやり取りとして実行できます。

続いて、このdaoを呼び出す処理ロジックを書きます。

src/main/java/jp/co/etlab/model/InsertLogic.java
	package jp.co.etlab.model;

	import jp.co.etlab.dao.InsertDAO;
	import jp.co.etlab.model.MemoData;
	
	public class InsertLogic {
		public boolean execute(MemoData md) {
			boolean st = true;
			try {
				st = InsertDAO.insertData(md);
			} catch (Exception e) {
				System.out.println(e.getMessage());
				st = false;
			}
			return st;
		}
	}

ということで、もともとのMain.javaを改造してデータべースに関わるところのLogicを呼び出せばよいようにしましょう。

で、ついでにMain.javaの場所をetlabの下のservletに移動して、中身をきれいにしましょう。PostはFormからのデータ受信用、Getは画面呼び出し用です。

src/main/java/jp/co/etlab/servlet/Main.java
	package jp.co.etlab.servlet;

	import java.io.IOException;
	
	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 jp.co.etlab.model.InsertLogic;
	import jp.co.etlab.model.MemoData;
	
	@WebServlet("/Main")
	public class Main extends HttpServlet {
		private static final long serialVersionUID = 1L;
	
		protected void doPost(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
			request.setCharacterEncoding("UTF-8");
			String smemo = request.getParameter("smemo");
			String scategory = request.getParameter("scategory");
			
			//Userインスタンスの生成
			MemoData md = new MemoData(smemo,scategory);
			
			//Insert処理
			InsertLogic insertLogic = new InsertLogic();
			boolean st = insertLogic.execute(md);
			
			//loginResultをフォワード
			RequestDispatcher dispatcher =
					request.getRequestDispatcher("/WEB-INF/jsp/main.jsp");
			dispatcher.forward(request, response);
		}
		protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
			RequestDispatcher dispatcher =
				request.getRequestDispatcher("/WEB-INF/jsp/main.jsp");
			dispatcher.forward(request, response);
		}
	}

さて、これでロジックが出来ましたが、あとViewのmain.jspを作って手入力でデータを追加する流れまで作りたいのですが、ここで少し View の見た目を少し考えて、Bootstrapの話を挟みます。

BootStrapで見た目を整える

いままで作ったjspは、どれもCSSを書いていません。そのため、見た目しょぼいです。この見た目がしょぼいというのは実は大問題で、WEB系の出来上がりを見たときに、きれいなものと、何もしてないものを比べると20倍くらい価値の差がでます。しかし、プログラマはとかくデザインは苦手。そこでBootstrapの力を借りましょう。

そこで、main.jspを作りながらこれをBootstrap対応にしていきます。まずはhtml5のひな形から開始

src/main/webapp/WEB-INF/jsp/main.jsp
	<!DOCTYPE html>
	<html lang="ja">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Document</title>
	</head>
	<body>
		
	</body>
	</html>

BootstrapはレスポンシブWEBデザインを実現するためのフレームワークで、 bootstrapサイトにあります。今回はインストールしない方法でやります。

Bootstrapサイトのgetting startのintroductionの 2.Include Bootstrap’s CSS and JS.にある、linkとscriptの2行をコピーして、貼り付けます

そのほか、bodyの内側に containerという名前のdivを作成し、各TABの中に class=で bootstrapのパラメータを書いていきます。

例えば、display-3は-1から-5までの大きさの中くらいの大きさ、bg-secondaryは2番目の色=灰色でbackgroudを塗りなさい。text-whiteで文字を白にするなどを設定できます。これらはCSSを書かずにHTMLの中にclassで指定するだけなので、プログラム的に記述出来てプログラムには分かりやすい書き方です。デザイナーには面倒でしょうけど。そして、DOCTYPEの前に、jspでUTF-8を宣言しておきます。これをしないと文字化けがおきます。

src/main/webapp/WEB-INF/jsp/main.jsp
	<%@ page language="java" contentType="text/html; charset=UTF-8"
		pageEncoding="UTF-8"%>
	<!DOCTYPE html>
	<html lang="ja">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>VsDBAccess</title>
		<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" 
		rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" 
		crossorigin="anonymous">
	</head>
	<body>
		<div class="container">
			<h1 class="display-3">VsDBAccess</h1>
			<p class="text-right">データベースアクセスサンプル</p>
			<footer class="text-center bg-secondary text-white">
				<p>copy right 2022 EtLab</p>
			</footer>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" 
		integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" 
		crossorigin="anonymous"></script>
	</body>
	</html>
Bootstrapサンプル

その他のやり方は、Bootstrapのdocumentを読んでください。

Formのある画面を作っていく

では、Bootstrapは作りながら覚えましょう。まず、formで囲みます。actionはMain.javaに渡したいので Main 。そしてinputで入力されたデータを POSTで渡したいので methodはPOSTにします。

そしてBootstrap的に、form-groupで囲んで、その中をlabelとinputで記述します。そこでclassをform-controlとして記述します。form-groupでまとめます。

src/main/webapp/WEB-INF/jsp/main.jsp
	<%@ page language="java" contentType="text/html; charset=UTF-8"
		pageEncoding="UTF-8"%>
	<!DOCTYPE html>
	<html lang="ja">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>VsDBAccess</title>
		<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" 
		rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" 
		crossorigin="anonymous">
	</head>
	<body>
		<div class="container">
			<h1 class="display-3">VsDBAccess</h1>
			<p class="text-right">データベースアクセスサンプル</p>
			<form action="Main" method="POST">
				<div class="form-group">
					<label for="smemo">忘備録</label>
					<input type="text" class="form-control" id="smemo" name="smemo" required>
				</div>
				<div class="form-group">
					<label for="scategory">カテゴリー指定</label>
					<input type="text" class="form-control" id="scategory" name="scategory">
				</div>
				<div class="form-group">
					<input type="submit" class="form-control btn btn-primary" value="追加">
				</div>
			</form>
			<footer class="text-center bg-secondary text-white mt-5">
				<p>copy right 2022 EtLab</p>
			</footer>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" 
		integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" 
		crossorigin="anonymous"></script>
	</body>
	</html>

そして、入力してみましょう。うまくいけば、main.jsp->Main.java->InsertLogic->InsertDAOとデータが渡り、MemoDataテーブルに1行書き込みができるはずです。

main.jspからデータ追加

データ一覧を取得する流れを作る

さきほど、Main.javaの中でInsertLogicからInsertDAOを呼び出す流れを作りました。それと同じでMain.javaの中でListLogicからListDAOを呼び出す流れを作り、main.jspを呼び出すときはいつも一覧を付けて呼び出すように改造しましょう。

まず、ListDAOを作ります。

src/main/java/jp/co/etlab/dao/ListDAO.java
	package jp.co.etlab.dao;

	import java.sql.Connection;
	import java.sql.DriverManager;
	import java.sql.PreparedStatement;
	import java.sql.ResultSet;
	import java.sql.SQLException;
	import java.util.ArrayList;
	import java.util.Date;
	
	import jp.co.etlab.model.MemoData;
	
	public class ListDAO {
		public static ArrayList getMemoData() throws ClassNotFoundException{
			Connection con = null;
			ArrayList am = new ArrayList<>();
			try {
				Class.forName("org.mariadb.jdbc.Driver");
			} catch(ClassNotFoundException e) {
				//
			}
	
			try {
				con = DriverManager.getConnection("jdbc:mariadb://localhost:3306/mydb","root","");
				//step2 送信すべきSQL文のひな形を準備
				PreparedStatement pstmt  = con.prepareStatement
					("SELECT * FROM MEMODATA");
	
				//DBMSに検索系を送信
				ResultSet r = pstmt.executeQuery();
				//処理結果を見る
					while(r.next()) {
					int aid = r.getInt("AID");
					String smemo = r.getString("SMEMO");
					java.sql.Timestamp ts = r.getTimestamp("STIME");
					long l = ts.getTime();
					Date d = new Date(l);
					int sst = r.getInt("SST");
					String scategory = r.getString("SCATEGORY");
					MemoData md = new MemoData(aid,smemo,d,sst,scategory); 
					am.add(md);
				}
				r.close();
				pstmt.close();
				return am;
			} catch (SQLException e) {
				e.printStackTrace();
				return null;
			} finally {
				if (con != null) {
					try {
						con.close();
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

このプログラムでMemoDataテーブルの内容一覧をArrayListにしてくれます。さてこのプログラムを呼び出す一覧処理を代行するプログラム ListLogic.javaを書きます。

src/main/java/jp/co/etlab/model/ListLogic.java
	package jp.co.etlab.model;

	import java.util.ArrayList;
	
	import jp.co.etlab.dao.ListDAO;
	
	public class ListLogic {
		public ArrayList execute() {
			ArrayList am = new ArrayList<>();
			try {
				am = ListDAO.getMemoData();
			} catch (Exception e) {
				System.out.println(e.getMessage());
			}
			return am;
		}
	}

あとは、このロジックをMain.javaで呼び出せばOKです。まずは最初のGetの呼び出しで一覧をデータを添えてフォワードするように変更します。

合わせて、PostのInsertの時も一覧が必要なので、同じ流れにします。

src/main/java/jp/co/etlab/servlet/Main.java
	<追加>
	import java.util.ArrayList;

	<追加>
	import jp.co.etlab.model.ListLogic;

	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
		<省略>
			InsertLogic insertLogic = new InsertLogic();
			boolean st = insertLogic.execute(md);
			<追加>
			ArrayList memoList = new ArrayList<>();
			ListLogic logic = new ListLogic();
			memoList = logic.execute();

			request.setAttribute("memoList", memoList);	

		protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
			<追加>
			ArrayList memoList = new ArrayList<>();
			ListLogic logic = new ListLogic();
			memoList = logic.execute();
	
			request.setAttribute("memoList", memoList);
			RequestDispatcher dispatcher =
				request.getRequestDispatcher("/WEB-INF/jsp/main.jsp");
			dispatcher.forward(request, response);
		}
	}

追加部分だけ記述します。続いて、フォワードされた方のmain.jspを改造して、受け取ったArrayListをターブルで表示するところです。

src/main/webapp/WEB-INF/jsp/main.jsp
	<%@ page language="java" contentType="text/html; charset=UTF-8"
		pageEncoding="UTF-8"%>
	<%@ page import="jp.co.etlab.model.MemoData" %>
	<%@ page import="java.util.ArrayList" %>
	<%@ page import="java.text.SimpleDateFormat" %>
	<%@ page import="java.util.Date" %>
	<%@ page import="jp.co.etlab.model.ListLogic" %>
	<%
	ArrayList<MemoData> am = (ArrayList<MemoData>) request.getAttribute("memoList");
	SimpleDateFormat sd = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
	%>
	<!DOCTYPE html>
	<html lang="ja">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>VsDBAccess</title>
		<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" 
		rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" 
		crossorigin="anonymous">
	</head>
	<body>
		<div class="container">
			<h1 class="display-3">VsDBAccess</h1>
			<p class="text-right">データベースアクセスサンプル</p>
			<form action="Main" method="POST">
				<div class="form-group">
					<label for="smemo">忘備録</label>
					<input type="text" class="form-control" id="smemo" name="smemo" required>
				</div>
				<div class="form-group">
					<label for="scategory">カテゴリー指定</label>
					<input type="text" class="form-control" id="scategory" name="scategory">
				</div>
				<div class="form-group">
					<input type="submit" class="form-control btn btn-primary" value="追加">
				</div>
			</form>
			<table class="table table-striped">
				<thead class="thead-dark"><tr><th>ID</th><th>忘備録</th><th>日付</th><th>状態</th><th>カテゴリ</th></tr></thead><tbody>
				<% if (am==null) { %>
					<tr><td>データがありません</td></tr>
				<% } else { 
				for (MemoData md: am) { %>
					<tr>
					<td><%= md.getAid() %></td><td><%= md.getSmemo() %></td><td><%= sd.format(md.getStime()) %></td>
					<td><%= md.getSst() %></td><td><%= md.getScategory() %></td>
					</tr>
				<% } }%>
				</tbody></table>
			<footer class="text-center bg-secondary text-white mt-5">
				<p>copy right 2022 EtLab</p>
			</footer>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" 
		integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" 
		crossorigin="anonymous"></script>
	</body>
	</html>

なにもなければ、データがありませんと表示し、あればテーブルに表示します。

Main 一覧表示

削除の流れを作ってみる

先ほどは、DAOから作って一覧を作りましたが、今度は逆に画面から作っていきましょう。さきほど作ったテーブル一覧の最後の列に削除のボタンを作り、各行に配置したボタンを押すと、Main.javaにGetで削除IDを送信するようにしてみましょう。

src/main/webapp/WEB-INF/jsp/main.jsp
	<table class="table table-striped">
	<thead class="thead-dark"><tr><th>ID</th><th>忘備録</th><th>日付</th>
		<th>状態</th><th>カテゴリ</th><th>消去</th></tr></thead><tbody>
	<% if (am==null) { %>
		<tr><td>データがありません</td></tr>
	<% } else { 
	for (MemoData md: am) { %>
		<tr>
		<td><%= md.getAid() %></td><td><%= md.getSmemo() %></td><td><%= sd.format(md.getStime()) %></td>
		<td><%= md.getSst() %></td><td><%= md.getScategory() %></td>
		<td><a href="Main?delete=<%= md.getAid() %>" class="btn btn-danger" role="button" 
			onclick="return confirm('消去してよろしいですか?');">消去</a></td>
		</tr>
	<% } }%>
	</tbody></table>

hrefでMain?delete=1とMainにGetを都バスと、Mainにparameterでdelete=1のデータが渡ります。ここを確認するために、Main.javaにprint文を入れて確認しましょう。

src/main/java/jp/co/etlab/servlet/Main.java
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String did = request.getParameter("delete");
		System.out.println("delete:"+did);

これでidが渡るようになるはずです。データが渡るか確認しましょう。

消去実験

1番の消去を押すと、JavaScriptの確認が出て、OKを押すと、コンソールにdelete:1が表示されます。

では、DeleteDAOを作りましょう。InsertDAO.javaをコピーして、DELETEにするぐらいで、できます。

src/main/java/jp/co/etlab/dao/DeleteDAO.java
	package jp.co.etlab.dao;

	import java.sql.Connection;
	import java.sql.DriverManager;
	import java.sql.PreparedStatement;
	import java.sql.SQLException;
	
	public class DeleteDAO {
		public static boolean deleteData(int aid ) throws ClassNotFoundException{
			Connection con = null;
			try {
				Class.forName("org.mariadb.jdbc.Driver");
			} catch(ClassNotFoundException e) {
				//
			}
	
			try {
				con = DriverManager.getConnection("jdbc:mariadb://localhost:3306/mydb","root","");
				//step2 送信すべきSQL文のひな形を準備
				PreparedStatement pstmt  = con.prepareStatement
					("DELETE FROM MEMODATA WHERE AID=?");
				//ひな形に値を流し込む
				pstmt.setInt(1,aid);
				//DBMSに検索系を送信
				int r = pstmt.executeUpdate();
				//処理結果を見る
				pstmt.close();
	
				if (r==1) {
					return true;
				} else {
					return false;
				}
			} catch (SQLException e) {
				e.printStackTrace();
				return false;
			} finally {
				if (con != null) {
					try {
						con.close();
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

続いて、消去処理をDeleteLogic.javaで作ります。

src/main/java/jp/co/etlab/model/DeleteLogic.java
	package jp.co.etlab.model;

	import jp.co.etlab.dao.DeleteDAO;
	
	public class DeleteLogic {
		public boolean execute(int aid) {
			boolean st = true;
			try {
				st = DeleteDAO.deleteData(aid);
			} catch (Exception e) {
				System.out.println(e.getMessage());
				st = false;
			}
			return st;
		}
	}

続いて、このDeleteLogicをMain.javaから呼び出します。

src/main/java/jp/co/etlab/servlet/Main.java
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String did = request.getParameter("delete");
		if (did != null) {
			DeleteLogic deleteLogic = new DeleteLogic();
			//System.out.println("delete=" + did);
			boolean st = deleteLogic.execute(Integer.parseInt(did));
		}

		ArrayList memoList = new ArrayList<>();

Main.javaのdoGetにDeleteLogicを呼び出すところを作ります。最初にコールされたときはパラメータがありませんから、その時は無視して、deleteパラメータが来たら消去を実行して、一覧を返します。

消去成功

今回は、ここまでで終了です。まだカテゴリーやステータスの対応が残っていますので、改造をしたい人はやってみてください。