🗄️

[DB]DAOパターンでの実装

2022/07/02に公開


◆はじめに

前回がまだの方は、こちらからお読みください。
DBAccessorに、SQL文を記述してデータベースに命令を送信する方法をご紹介ました。

https://zenn.dev/nakohama/articles/35451633ee464b

今回は、「DAOパターン」(通称:DAO)を利用して、
画面の挙動としては同じですが、より便利に
データベースに命令を送信する方法をご紹介します。


「select」「insert」「update」「delete」ボタンがあり、
データベースにデータを送信したり、呼び出したりできます。
「select」ボタンを押すと、データベースに登録されていた文字が表示されます。
今回は、「select」のみDAOで動作する実装になっています。


◆DAOパターンとは

「Data Access Object パターン」の略です。通称DAOです。
DAOは、DAOクラスを作成してオブジェクトやリストの形でデータベースに送ったものを、
途中でSQLの命令文に勝手に変換してくれます。



データベースのアクセスにDAOを利用することで、
例えば、DAOによういしてあるselectのメソッドを呼び出せば良いので、
汎用性があり、保守性が高くなるというメリットがあります。


実装するにあたっては、
①データベースのテーブルのレコードに対応したテーブルクラス
② ①のテーブルクラスに対するDAOのクラス
③ テーブルクラスとDAOのクラスを使用してデータベースにアクセスするコード
が必要です。


◆前提/環境など

本記事は、以下の記事の「InputFunction」プロジェクトをベースに作成します。
また、データベースは、HSQLDBを扱います。
Echo機能のServletの処理時間を計測するFilterを実装しています。
また、Sessionで結果を保持するようになっています。
過去の記事の内容を踏まえた前提で、記事は書いていますのでご了承ください。


仕様は以下です。
<Echo機能> ・文字列を入力し、送信ボタンを押すと、送信した文字列が画面に表示される。
<Validation機能> ・送信された文字列が空欄の場合は,「この項目は必須入力です。」と文字列が表示される。
<TimeFiletr機能(Listener)> ・Servletの処理時間を計測し、コンソールに表示
<Session機能> ・処理結果をSessionがリセットされるまで保持する


※本記事では、 eclipseは以下のバージョンでの画像を使用しています。
日本語化はしていません。
他のversionでの動作は確認しておりません。


◆手順

それでは、実装していきます。
今回は、「select」のみDAOで動作する実装になっています。
最後に動作確認をしたら終了です。


①ディレクトリとファイルの作成

最終的なディレクトリは、下記のようになります。

・「dao」というパッケージを作成し、
・daoのフォルダの中に、「Textdata.java」と「TextdataDao.java」を作成


②ソースコード

・Textdata.javaのソースコード

package dao;

public class Textdata{
	
	private String text;
	
	public void setText(String text) {
		this.text = text;
	}
	
	public String getText() {
		return text;
	}
	
	@Override
	public String toString() {
		return "Textdata [ text = " + text + " ] ";
	}
}

・DAOのソースコード

textdataDao.java
package dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

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 javax.servlet.http.HttpSession;

public class TextdataDao {
	static {
		String driver = "org.hsqldb.jdbcDriver";
		
		try {
			Class.forName(driver);
		} catch(ClassNotFoundException e){
			throw new RuntimeException(e);
		}
	}

private static Connection getConnection() throws SQLException{
	

     String url = "jdbc:hsqldb:hsql://localhost/mydb/textdb";
	 String user = "SA";
	 String password = "";
	 
	 Connection connection = DriverManager.getConnection(url , user , password);
	 connection.setAutoCommit(false);
	 
	 return connection;
 }

public List<Textdata> selectAll(HttpServletRequest request) throws SQLException{
	
	Connection connection = getConnection();
	String sql = "SELECT * FROM textdata";
	PreparedStatement statement = connection.prepareStatement(sql);
	
	List<Textdata> ret = new ArrayList<Textdata>();
	  HttpSession session = request.getSession();  
	  ArrayList<String> textlist = new ArrayList<String>();	  
	  int count = 0;  
	ResultSet rs = statement.executeQuery();
	
	while (rs.next()) {
		Textdata textdata = new Textdata();
		String Text =rs.getString("text");
		 textdata.setText(Text);
		
		System.out.println(Text);	
		  textlist.add(Text);	 			
			count ++ ;
			
	}
	session.setAttribute("SQLmessage","読込成功"); 
	session.setAttribute("Resultmessage",textlist);  	
	
	 if(count == 0) {
		  session.setAttribute("Resultmessage","登録されているテキストデータはありません");  	
	  }  
	 
	rs.close();
	statement.close();
	connection.close();
	
	return ret;
}

public int insert (Textdata textdata) throws SQLException {
	
	Connection connection = getConnection();
	
	String getIdsql = " SELECT NEXT VALUES FOR my_seq "
			          + " FROM information_schema.system_tables "
			          + " WHERE table_name = 'SYSTEM_TABLES' " ;
	PreparedStatement statement = connection.prepareStatement(getIdsql);
	ResultSet rs = statement.executeQuery();
	rs.next();
	//int id = rs.get)nt(1);
	rs.close();
	statement.close();
	
	//textdata.setId(id);
	
	String sql = " INSERT INTO textdata (text) VALUES (?) ";
	
	statement = connection.prepareStatement(sql);
	
	//statement.setInt(1, id);
	//statement.setInt(2, textdata.getText());
	//statement.setInt(1, id);
	
	int updateCount = statement.executeUpdate();
	
	statement.close();
	
	connection.commit();
	connection.close();
	
	return updateCount;
}


}

・DBAccessor.javaのソースコード

DBAccessor.java
package dbaccessor;

import dao.Textdata;
import dao.TextdataDao;
import java.util.List;

import java.util.ArrayList;
import java.io.IOException;

import javax.security.auth.message.callback.PrivateKeyCallback.Request;
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 javax.servlet.http.HttpSession;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;



//対応するjspのFormのaction名
  @WebServlet(urlPatterns = {"/dbaccess"})  
  
//Validation機能を持たせたEchoサーブレットクラス
public class DBAccessor extends HttpServlet{
	  
		private static final long serialVersionUID = 1L;
		
		private static final String driver = "org.hsqldb.jdbcDriver";
		private static final String url = "jdbc:hsqldb:hsql://localhost/mydb/textdb";
		private static final String user = "SA";
		private static final String password = "";
		

//画面からPostされた場合に起動するメインとなるメソッド
	@Override
	protected void doPost(HttpServletRequest request , HttpServletResponse response)throws ServletException,
IOException {
		
		String name = request.getParameter("SubmitType");
		
		switch(name) { 
	    case "select":
		
		TextdataDao textdataDao = new TextdataDao();
		
		List<Textdata> alltextdata;
		try {
			alltextdata = textdataDao.selectAll(request);
			
			printData(alltextdata);
			
			Textdata textdata = new Textdata();
			textdata.setText("テキストデータDao");
			
			alltextdata = textdataDao.selectAll(request);
			printData(alltextdata);
			
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    	break;
	    	
	    case "insert":
	    	try {
				Class.forName(driver);
				Connection	connection = DriverManager.getConnection(url,user,password);
				connection.setAutoCommit(false);
				insert(connection,request);
				connection.commit();
				connection.close();
				
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	break;
	    	
	    case "update":
	    	try {
				Class.forName(driver);
				Connection	connection = DriverManager.getConnection(url,user,password);
				connection.setAutoCommit(false);
				update(connection,request);
				connection.commit();
				connection.close();
				
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	break;
	    	
	    case "delete":
	       	try {
				Class.forName(driver);
				Connection	connection = DriverManager.getConnection(url,user,password);
				connection.setAutoCommit(false);
				delete(connection,request);
				connection.commit();
				connection.close();
				
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	break;
	    	
	    default:
			//それ以外の処理
			System.out.println("error");
			break;
			
		}
	
		
		//リダイレクト
   //コンテキストルート(InputFunction)の取得
		String contextPath = getServletContext().getContextPath();
		//リダイレクトpathを設定(表示させるページ→echo.jsp)
		String path = contextPath + "/echo.jsp";
		//実際にリダイレクトを行っている関数
		response.sendRedirect(path);

	}
	
	
	private void printData(List<Textdata> alltextdata) {
		for (Textdata textdata : alltextdata) {
			System.out.println(textdata);
		}
		System.out.println();
	}
	
	  //Insert
	  protected void insert(Connection connection,HttpServletRequest request) throws SQLException {
		  Statement statement = connection.createStatement();  
		  HttpSession session = request.getSession();   
		 try{
		  String inserttext = session.getAttribute("message").toString();  
			 
		  String sql = "INSERT INTO textdata (text) VALUES('" +inserttext + "')";
		  int updateCount = statement.executeUpdate(sql);
		  
		  if (updateCount == 1) {
			  session.setAttribute("SQLmessage","登録成功");
			  System.out.println("登録成功");
		  }   else {
			  session.setAttribute("SQLmessage","登録失敗");
			  System.out.println("登録失敗");
		  }
		} catch (RuntimeException e) {
			session.setAttribute("SQLmessage","登録失敗");
			System.out.println("登録失敗");
			statement.close();
			return;
		}
		  statement.close();
	  }
	  
	  //Update
	  protected void update(Connection connection,HttpServletRequest request) throws SQLException {
		  Statement statement = connection.createStatement();  
		  HttpSession session = request.getSession();  
		  try {
			  String updatetext = session.getAttribute("message").toString();
			  
			  String sql = "UPDATE textdata SET text = 'Updateテキストデータ' WHERE text = '"+updatetext+"'";
			  int updateCount = statement.executeUpdate(sql);	
		  
			  if (updateCount == 1) {
				  session.setAttribute("SQLmessage","更新成功");
				  System.out.println("更新成功");
			  }  else {
				  session.setAttribute("SQLmessage","更新失敗");
				  System.out.println("更新失敗");
			  }	  
		  } catch (RuntimeException e) {
			  session.setAttribute("SQLmessage","更新失敗");
			  System.out.println("更新失敗");
			  statement.close();
			  return;
		  }
		  	statement.close();
	  }
	  
	  protected void delete(Connection connection , HttpServletRequest request) throws SQLException {
		  Statement statement = connection.createStatement();
		  String sql = "DELETE FROM textdata ";
		  HttpSession session = request.getSession();  
		  int updateCount = statement.executeUpdate(sql);
		  
		  if (updateCount >= 1) {
			  session.setAttribute("SQLmessage","削除成功");
			  System.out.println("削除成功");
		  } else {
			  session.setAttribute("SQLmessage","削除失敗");
			  System.out.println("削除失敗");
		  }  
		  statement.close();
	  }
	
}

・jspのソースコード

echo.jsp
<%@page language="java" contentType = "text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page isELIgnored= "false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>Echo機能+Validation機能+TimeFilter機能(Listener)+Session機能+リロード対策+DB機能(DAO)</title>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>

<body>
	
 <h3>Echo機能+Validation機能+TimeFilter機能(Listener)+Session機能+リロード対策+DB機能(DAO)</h3>
 
   <%-- リセットのリクエストパラメータを渡す--%>
 <a href="echo?reset">セッションのリセット</a>

  <%-- 入力フォーム --%>
 <form action="echo" method="post">
  <br />入力してください : 
  
  <%-- テキストボックス(m) --%>
  <input type="text" name="m" />
  
   <%-- Validationメッセージの出力  --%>
   <%-- var="vm" → c:out で valueにセットする際に使う名称   --%>
   <%-- [' ']には、 MessageForm.javaのテキストボックスのメッセージ保持用のパラメータ名を入れる   --%>
 <c:forEach items="${validationMessage['textMessage']}" var="vm">
   <c:out value="${vm}"/>
 </c:forEach>
 
<br />
 
 <%-- 送信ボタン --%>
  <input type="submit" /> <br />

 </form>
 
 <br />
 
 
  <%-- Echoメッセージの出力--%>
DB送信文字列 :
 <c:if test="${ not empty message }">
「${ message }」です。
 </c:if>
 
 
  <br />
  
   <%-- DBAccessフォーム --%>
 <form action="dbaccess" method="post" name="DataBase" onsubmit="return SQL()" >

  <%-- Selectボタン --%>
<input type="submit" value="Select" onclick="DataBase.SubmitType.value='select'"  />
  <%-- Insertボタン --%>
<input type="submit" value="Insert" onclick="DataBase.SubmitType.value='insert'"  />
  <%-- Updateボタン --%>
<input type="submit" value="Update" onclick="DataBase.SubmitType.value='update'"  />
  <%-- Deleteボタン --%>
<input type="submit" value="Delete" onclick="DataBase.SubmitType.value='delete'"  />

 <c:if test="${ not empty SQLmessage }">
「${ SQLmessage }」
 </c:if>

<input name="SubmitType" type="hidden" value="" />
  
 </form>
 
  <br />
 
   <%-- SQL結果の出力--%>
 <c:if test="${ not empty Resultmessage }">
  ${ Resultmessage }
 </c:if>
 
    <%-- SQL結果の出力--%>
 <script type="text/javascript">
function SQL() {
	 if (DataBase.SubmitType.value == 'select') {
	    }
	 if (DataBase.SubmitType.value == 'insert') {
	    }
	 if (DataBase.SubmitType.value == 'update') {
	    }
	 if (DataBase.SubmitType.value == 'delete') {
	    }
	    return true;
}
</script>


  
</body>
DB機能に関係するコードは以上です。
それ以外のファイルのコードなどは、
別の記事をご覧ください。


③動作確認

実装ができたら
・Tomcatを起動
・以下のURLにアクセス

http://localhost:8080/InputFunction/echo.jsp

以下の画面が表示されます

今回は、「select」のみDAOで動作する実装になっていますので、
それでは、select文の動作を確認していきましょう。
まず、
・テキストボックスに「テキストデータ」と入力

・「insert」ボタンを押す
・「select」ボタンを押してデータを表示
下記のように表示されたら、OKです。

その他の、insert,updateやdeleteに関しては、
前回と同じ、DAOを使用していない状態での実装です。
そちらのDAOでの実装は、また機会があればご紹介したいと思います。


◆さいごに

以上です。いかがだったでしょうか。
以下のまとめ記事もどうぞご覧ください。
最後まで、ご覧いただきありがとうございました。

https://zenn.dev/nakohama/articles/d505c637903339


◆参考

本記事は、以下の書籍を大いに参考にしています。
より詳しく知りたい方は、どうぞ。

https://www.amazon.co.jp/dp/4797362596

Discussion