Database/JDBC/Tomcat/Eclipse (Debian11.4.0)

2022/7/30


RDBMS

JavaBeansからデータベースに接続して、電話番号と部屋名が検索できる電話番号簿をつくる。
RDBMS(Relational DataBase Management System)には選択肢があるが、PostgreSQL13.7を使う。

準備

JavaBeansとデータベースはJDBC接続する。JDBCドライバがTomcat(catalina)にインストールされていることを確認する。
postgresql.jar(postgresql-jdbc4.jar)があればOK
postgresql.jarがない場合はコピー(またはダウンロード)する。
ls ~/app/tomcat10/lib/postgresql*
#cp /usr/share/java/postgresql.jar ~/app/tomcat10/lib/
#wget -O app/tomcat10/lib/postgresql-42.4.0.jar https://jdbc.postgresql.org/download/postgresql-42.4.0.jar
データベースにはすでにつぎのテーブルが用意ができているものとする。
同名のテーブルがあるときはテーブルを作り直そう。
テーブル名:sample
tel room
6447 高橋研究室
6547 情報通信実験室

テーブル名:sample
colum type制約その他
tel INTEGER PRIMARY KEY内線番号は4桁(1000〜9999)
room TEXT NOT NULL
#データベースに接続
psql データベース名

#テーブル新規作成
CREATE TABLE sample(tel INTEGER PRIMARY KEY, room TEXT NOT NULL);

#データを挿入
INSERT INTO sample(tel,room) VALUES (6447,'高橋研究室'),(6547,'情報通信実験室');
SELECT * FROM sample;

方針

index.htmlを修正

検索ボタンを押した時、別々のサーブレットに処理をさせたい。index.htmlを修正しよう。
jdbc

Myservlet1.java,Myservlet2.javaをつくる

さきほどのMyservlet.javaを参考にサーブレットMyservlet1.java,Myservlet2.javaをつくる。
Myservlet1は「電話番号から検索」を担当する。Myservlet2は「部屋から検索」を担当する。
Myservlet1.java,Myservlet2.javaはほぼ同じ内容なので、間違えないようにタイプしてほしい。
Myservlet1.javaMyservlet2.java
package myapp;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class Myservlet1 extends HttpServlet {
	private static final long serialVersionUID = 20220730L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		MyBeans mybeans = new MyBeans();
		mybeans.setTel(req.getParameter("tel"));
		mybeans.setSubmit(req.getParameter("submit"));
		try {
			mybeans.query1();
		} catch (Exception ex) {
			throw new ServletException(ex);
		}
		//MyBeansクラスをリクエスト属性にセット
		req.setAttribute("MyBeans", mybeans);
		//つづきはmyjsp.jspへ
		this.getServletContext().getRequestDispatcher("/myjsp.jsp").forward(req, resp);
	}
}
package myapp;

import java.io.IOException;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class Myservlet2 extends HttpServlet {
	private static final long serialVersionUID = 20220730L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		MyBeans mybeans = new MyBeans();
		mybeans.setRoom(req.getParameter("room"));
		mybeans.setSubmit(req.getParameter("submit"));
		try {
			mybeans.query2();
		} catch (Exception ex) {
			throw new ServletException(ex);
		}
		//MyBeansクラスをリクエスト属性にセット
		req.setAttribute("MyBeans", mybeans);
		//つづきはmyjsp.jspへ
		this.getServletContext().getRequestDispatcher("/myjsp.jsp").forward(req, resp);
	}
}

web.xmlを修正

サーブレットが増えたのでweb.xmlを修正する。
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
	<servlet>
		<servlet-name>myservlet20220728</servlet-name>
		<servlet-class>myapp.Myservlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>myservlet20220728</servlet-name>
		<url-pattern>/Myservlet</url-pattern>
	</servlet-mapping>

	<servlet>
		<servlet-name>myservlet202207301</servlet-name>
		<servlet-class>myapp.Myservlet1</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>myservlet202207301</servlet-name>
		<url-pattern>/Myservlet1</url-pattern>
	</servlet-mapping>

	<servlet>
		<servlet-name>myservlet202207302</servlet-name>
		<servlet-class>myapp.Myservlet2</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>myservlet202207302</servlet-name>
		<url-pattern>/Myservlet2</url-pattern>
	</servlet-mapping>
</web-app>

myjsp.jspを修正

ほとんど中身がないように見えるが、大事な部分はMyBeansがつくるのでこれでよい。
<%@ page contentType="text/html; charset=utf-8" %>
<jsp:useBean id="MyBeans" class="myapp.MyBeans" scope="request" />
<html>
<head>
<title>myjsp</title>
</head>
<body>
	<h1>電話番号・部屋</h1>
	<jsp:getProperty name="MyBeans" property="table" />
</body>
</html>

MyBeansを修正

RDBMSと通信するためにいくつかのプロパティとメソッドを追加する。
すこしはプログラムらしくなった気がする。
MyBeansにアレコレ突っ込んだけど、本当はRDBMSに関する部分(RDBMSクラス)とMyBeans固有の部分(MyBeansクラス)に分けたい。
package myapp;
import java.sql.*;
public class MyBeans {
	String sql="";
	Connection con=null;
	Statement st=null ;
	ResultSet rs=null;
	final String lf="\n";
	String table;
	
	Integer tel;
	String room,submit;

  (途中省略)
// --- ここから追記 ---
	public void query1() {//電話番号から部屋を検索
		sql="SELECT tel,room FROM sample WHERE tel=" + tel + ";";
		execquery();
	}
	
	public void query2() {//部屋から電話番号を検索
		sql="SELECT tel,room FROM sample WHERE room='" + room + "';";
		execquery();
	}
	
    private void execquery() {
    	String url = "jdbc:postgresql://192.168.xx.xx:5432/db19000";
    	String username = "19000";
    	String password = "xxxxxxxx";
    	try {
    		Class.forName("org.postgresql.Driver");
    		con = DriverManager.getConnection(url, username, password);
    		st = con.createStatement();
    		rs = st.executeQuery(sql);
    		table="<table border='1'>";
    		table+="<tr><th>電話番号</th><th>部屋</th></tr>" + lf;
    		String msg="<tr><td colspan='2'>該当しませんでした</td></tr>";
    		while (rs.next()) {
    			msg="<tr>";
    			msg+= "<td>" + rs.getInt("tel")  + "</td>";
    			msg+= "<td>" + rs.getString("room").trim() + "</td></tr>" + lf;
    		}
    		table+= msg +"</table>" + lf;
    		rs.close();	st.close();	con.close();
    	} catch (Exception ex) {
    		table="DB error:" + lf + ex.toString();
    		System.out.println("DB error:"+lf+ex.toString() + lf + sql);
    	}
    }
}

動作確認

電話番号で検索、部屋で検索どちらも同じように見えるが(MyBeans.execquery()は共通だし、表示はmyjsp.jspだ)、よく見ると違いがある。
アドレスバーを見ると「電話番号で検索」はMyservlet1で処理したことがわかる。  アドレスバーを見ると「部屋で検索」はMyservlet2で処理したことがわかる。
jdbc jdbc

おまけで「知らない電話番号」を検索したときの処理も加えた。
jdbc

いつまでも「知らない電話番号」のままでは不便だ。
つぎは電話番号を登録してみよう。
Java Platform, Standard Edition & Java Development Kit バージョン11 API仕様
https://docs.oracle.com/javase/jp/11/docs/api/index.html