フレサーモン難民

備忘録など ほぼ自分向けのまとめ

WEBアプリとPostgreSQLを接続

Employee.java

package model;

import java.io.Serializable;

public class Employee implements Serializable {

	private String id;
	private String name;
	private int age;

	public Employee(String id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
	public String getId() { return this.id; }
	public String getName() { return this.name; }
	public int getAge() { return this.age; }
}

EmployeeDAO.java

package 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.List;

import model.Employee;

public class EmployeeDAO {

	private final String JDBC_url = "jdbc:postgresql://localhost:5432/example";
	private final String JDBC_user = "postgres";
	private final String JDBC_pass = "password";

	public List<Employee> findAll() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rSet = null;

		List<Employee> empList = new ArrayList<Employee>();

		try {
			Class.forName("org.postgresql.Driver");
			System.out.println("データベースに接続しました");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

		try {
			conn = DriverManager.getConnection(JDBC_url, JDBC_user, JDBC_pass);
			pstmt = conn.prepareStatement("select * from employee");
			rSet = pstmt.executeQuery();

			while(rSet.next()) {
				String id = rSet.getString("id");
				String name = rSet.getString("name");
				int age = rSet.getInt("age");

				Employee employee = new Employee(id, name, age);

				empList.add(employee);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}

		return empList;
	}

}

index.jsp(配置するのはWEB-INFディレクトリ)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="dao.EmployeeDAO,model.Employee,java.util.List,java.util.ArrayList" %>
<%
EmployeeDAO employeeDAO = new EmployeeDAO();
List<Employee> empList = employeeDAO.findAll();
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>あはあ</title>
</head>
<body>
<h1></h1>

<% for(Employee employee : empList) { %>
<p>
ID:<%= employee.getId() %><br>
名前:<%= employee.getName() %><br>
年齢:<%= employee.getAge() %>
</p>
<% } %>
</body>
</html>

JDBC

JDBC APIJavaプログラムからデータベースを利用する際に必要になるクラス

主なクラスには以下のものがある。またjava.sqlパッケージに含まれてる。

DriverManager:データベースへの接続の準備
Connection:データベースへの接続や切断
PreparedStatementSQL文の送信
ResultSet:データベースから検索結果を受け取る

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

public class ...

Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rset = null;

String JDBC_URL = "jdbc:postgresql://localhost:5432/DB名";
String JDBC_USER = "postgres";
String JDBC_PASS = "~~~~~~";

try {

  // データベースの接続
  conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASS);

  /* *******************************
    DB操作処理をするメイン処理部分
  ******************************** */

} catch ( SQLException e ) {
  e.printStackTrace();
}

DB操作処理部分

更新系SQLの場合:INSERT、UPDATE、DELETE

例:

PreparedStatement pstmt = conn.prepareStatement("delete from employee where age <= ?");

pstmt.setInt(1, 40);
int r = pstmt.executeUpdate();

if (r != 0) {
  System.out.println(r + "件の情報を削除しました。");
} else {
  System.out.println("該当する情報はありませんでした。");
}
pstmt.close();
PreparedStatementクラスで、SQL文のひな型を準備する。
PreparedStatement pstmt = conn.prepareStatement(SQL文のひな型);
SQL文のひな型に値を入れる。

下の他にもsetDouble()、setDate()などがある。

pstmt.setInt(パラメータ番号, 数値);
pstmt.setString(パラメータ番号, 文字列);
SQL文を送信する:PreparedStatemtntクラスのexecuteUpdate()メソッド

「処理の結果変更された行数」が戻り値で返される。
更新系のSQL文(UPDATE、INSERT、DELETE)では送信は全てこのメソッドで行える。

int r = pstmt.executeUpdate();

検索系SQL(SELECT)の場合

検索系SQLでも、PreparedStatementクラスでSQL文のひな型を準備し、それにset〇〇メソッドで値を入れるまでは更新系SQLと同じ。検索系SQLでは、SQL文を実行する際に用いるメソッドが更新系SQLとは異なる。

検索系SQL文の送信
ResultSet rset = pstmt.executeQuery();


ResultSetオブジェクトの持つ主なメソッド

next():戻り値はboolean、注目する行を1つ進め、成功したらtrue、すでに最終行の場合はfalseを返す。
getInt(列番号)、getInt(列の名前):指定した列の整数値を取り出す。
getString(列番号)、getString(列の名前):指定した列の文字列を取り出す。

検索系SQL文を送信して返り値として戻されたResultSetオブジェクトには、検索系のSQL文で注目した1行分の情報しか入っていない。

while( rset.next() ){
  System.out.println(rset.getString("NAME"));
}

めも

色々メモ

PostgreSQLに、AUTO_INCREMENT属性はない

(現在読んでる「スッキリわかるサーブレット&JSP入門 第2版」で使われてるH2 DatabaseにはAUTO_INCREMENT属性があるが、自分が使ってるPostgreSQLには無い)

SERIAL型を使うといいみたい。

create table student (
  id serial not null,
  name varchar(20),
  primary key(id)
);
ソート

order byを使うと、結果を昇順/降順でソートすることが出来る。ascもしくは省略で昇順になり、descをつけると降順となる。

order by カラム名 asc/desc
select * from テーブル order by カラム desc;
JavaプログラムとPostgreSQLを接続する

※この欄は一時的な個人的メモ書き
動的WEBプロジェクト名を右クリック→ビルド・パス→ビルド・パスの構成で、ライブラリーのモジュールパスに外部JARを追加でJDBCドライバのJARファイルを適用すれば接続できる。

WEBアプリ上でPostgreSQLと接続させる方法をこれから試す。WEB-INF/libにJARファイルを配置してみて試す。

PostgreSQLで作成したデータベースにJavaから接続できました。

PostgreSQLのインストールや、PostgreSQLでのデータベース作成はまあ問題なくいけたんですが、JDBCドライブのインストール関連のとこで何か手間取ったので備忘録として残します。

STEP1:JDBCドライブをインストールする

PostgreSQL JDBC Download

解凍するとpostgresql-〇.〇.〇.jarといった名前のファイルができる。

*** STEP2:JDBCドライブのjarファイルを、Eclipseのプロジェクト直下に「lib」という名前のフォルダを作りそこに入れる。

STEP3:Eclipseのプロジェクトのビルド・パスの構成にJDBCドライブのjarファイルを追加する。

プロジェクト名のとこで右クリック→「ビルド・パス」→「ビルド・パスの構成」を選択。「ライブラリー」より「外部JARの追加」でJDBCドライブのjarファイルを追加する。追加するとEclipseのプロジェクト内に「参照ライブラリー」が出来てる。

7/10修正:JDBCドライブのjarファイルを、動的Webプロジェクトを追加したアプリケーションサーバーのlibフォルダ上に置いておくことでJavaプログラムからPostgreSQLが利用できました。たとえば自分の環境では、動的Webプロジェクトに追加したサーバーがtomcat9だったので、C:\pleiades\tomcat\9\libにjarファイルを設置。

今回書いたJavaのコードは以下の通り。
データベース名"school"に、身長(height)、名前(name)の2つのカラムを持つテーブル"student"を作成し、全てのレコードを取り出して出力させています。ちなみにこちらの記事に記載されたコードのほぼ丸写しです。
qiita.com

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

public class PostgreExample {
  public static void main(String[] args){

    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rSet = null;

    String url = "jdbc:postgresql://localhost:5432/school";  // データベース"school"
    String user = "postgres";
    String pass = "password";

    try {
      conn = DriverManager.getConnection(url, user, pass);
      pstmt = conn.prepareStatement("select * from student");  // studentというテーブルの要素を取り出す
      rSet = pstmt.executeQuery();

      while(rset.next()) {
        String height = rSet.getString("height");
        String name = rSet.getString("name");

        System.out.println("身長:" + height);
        System.out.println("名前:" + name);
      }

    }
    catch (SQLException e) {
      e.printStackTrace();
    }
  }

}

H2 Databaseでやろうとしたけどもサーバモードでしようとしたらエラーが出てググってもわからんかったのでPostgreSQLでしてみる

テーブル
列:カラム、フィールドともいう
行:レコード、タプルともいう

例えば「野菜テーブル」が
名前   色   値段
トマト  赤   150
なす   紫   180
ピーマン 緑   120
とあったとすると、名前の一覧である「トマト、なす、ピーマン」が列であるカラム、フィールド。また「トマト、赤、150」の情報が行であるレコード、タプルとなる。

操作:データベース関連

データベースの一覧を見る
¥l
データベースを作る
create データベース名;
現在接続してるデータベースとは別のデータベースに接続する
¥c データベース名
データベース名を変更する
alter database 元の名前 rename to 新しい名前;
データベースを削除する
drop database データベース名;

操作:テーブル関連

テーブルを作る
create table テーブル名 (カラム名 データ型, カラム名 データ型, ...);
テーブル名を変更する
alter table 元の名前 rename to 新しい名前;
テーブルを削除する
drop table テーブル名;
テーブルを表示する
¥dt
テーブルの構造を見る
¥d テーブル名

データ操作

テーブルにデータを追加する

特定のカラムにデータを追加する場合は次のように書ける。

insert into テーブル名 (カラム名1 カラム名2,,,) values (値, 値, ...);

全てのカラムにデータを追加する場合は、カラム名の記述が省略でき、

insert into テーブル名 values (値, 値, ...);

と書ける。

複数のデータをまとめて追加する場合は

insert into テーブル名 values (値, 値, ...), (値, 値, ...), (値, 値, ...), ...

という風になる。

データを取得する

テーブルに定義されたすべての値を取得する場合は

select * from テーブル名;

となる。特定のカラムのデータを取得する場合は

select カラム名1, カラム名2... from テーブル名;

となる。

conn = DriverManager.getConnection( 
"jdbc:postgresql://localhost:5432/postgres", "postgres", "password");

データベースを利用する:JDBC

データベース

リレーショナルデータベース:テーブル(表)の形式でデータを管理しているデータベースの総称

レコード:リレーショナルデータベースにおいて、1件分のデータを表した1行のこと

データベースのデータ管理はDBMS(データベース管理システム)というソフトウェアが行っている。データベースを操作するということは、DBMSに指示を送り操作することである。

DBMSとデータベースはセットで動作するので、両者をあわせて「データベース」と呼ぶことも多い。

データベースを操作する専用言語としてSQL(Structured Query Language)が多く用いられている。SQLでは次の

SELECT文:レコードを検索
INSERT文:レコードを追加
UPDATE文:レコードを変更
DELETE文:レコードを削除

の4つの命令を使ってデータを操作する。

JDBCプログラム

データベースを利用するJavaプログラムのことをJDBCプログラムという。JDBCプログラムには、以下の2つが必要となる。

java.sqlパッケージに含まれるクラスやインタフェース

JDBCドライバというライブラリ

java.sqlパッケージはJava SEの標準APIで提供されているが、JDBCドライバは利用するデータベースの開発元から入手してこないといけない。

java.sqlパッケージ

java.sqlパッケージに含まれるクラスやインタフェースを利用することで、JavaプログラムからデータベースにSQLを送信して、データベースから結果を受け取ることができる。

java.sqlパッケージに含まれる主なクラス・インタフェースには以下のものがある。

DriveManagerDBMSへの接続準備を行う
ConnectionDBMSへの接続や切断を行う
PrepareStatementSQLへの送信を行う
ResultSetDBMSから検索結果を受け取る
SQLException:データベースに関するエラー情報を提供する

JDBCドライバ

JDBCドライバとは、データベースを操作するために必要となるクラスやインタフェース群。JDBCドライバに格納されたクラスやインタフェースは直接使用することはなく、java.sqlパッケージのクラスやインタフェースを介して間接的に使用する。



参照:「スッキリわかるサーブレットJSP入門 第2版」

フィルタ

フィルタとは

サーブレットに用意された特別なクラス。文字コードの設定など、同じ処理が複数のサーブレットクラスがある場合、その処理をフィルタにまとめることができる。

フィルタのメソッドに記述された処理は、サーブレットクラスのdoGet()およびdoPost()メソッドが実行される前後のタイミングで自動的に実行される。なので、フィルタを複数のサーブレットクラスに設定することで、それらのサーブレットクラスで共通する処理をまとめることができる。

また、ひとつのサーブレットクラスに複数のフィルタを設定し連続で実行することもできる(フィルタチェーン)。

フィルタの例

package filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter("/*")
public class FilterSample implements Filter {
  public void init(FilterConfig fConfig) throws ServletException { }
  public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
      request.setCharacterEncoding("UTF-8");
      chain.doFilter(request, response);
    }
    public void destroy() { }
  }
}

WebFilterアノテーション

WebFilterアノテーションで、フィルタを設定するサーブレットクラスを指定する。すべてのサーブレットクラスにそのフィルタを指定する場合は

@WebFilter("/*");

となる。

Filterインタフェースの実装

フィルタはjavax.servlet.Filterインタフェースを実装して作成する。このインタフェースには、フィルタがインスタンス化された直後に実行されるinit()、フィルタのインスタンスが廃棄される直前に実行されるdestroy()、そして設定されたサーブレットクラスがリクエストされたときに実行されるdoFilter()の3つのメソッドが定義されていて、フィルタを作成する際はこれらを全て実装しないといけない。

doFilter()メソッド

doFilter()メソッド内の

chain.doFilter(request, response);

より前の部分に記述した処理は前処理、後の部分に記述した処理は後処理になる(サーブレットクラスのdoGet()/doPost()メソッドが実行される前か後か?)

文字コードの設定は前処理になる。

参照:「スッキリわかるサーブレットJSP入門 第2版」