Tips

Apache Commons Javaプログラム演習問題 第16回

Apache Commons Javaプログラム演習問題 第16回

Apache Commons を利用した Java でのプログラム作成問題の16回目となります。

環境を構築していない場合は、概要を読み、環境を構築してから実施してください。

※この出題形式に関しては答えは1つではありません。
解答例はできるだけ複数載せるつもりですが、問題文の要件を満たしていれば正解として下さい。

準備

今回からDBへの接続プログラムを問題として出していきます。
DBの環境構築を行ってください。

問題では、MariaDBを利用しています。
Windows環境の場合は、XAMPPをインストールしてください。

XAMPPの場合は、phpMyAdminが利用できますので、DB操作はそちらを利用すると楽です。
ブラウザを開き、http://localhost/phpmyadmin/にアクセスすれば、見れるはずです。

まず、Databaseを作成します。
この問題では、tech_pjinとしています。

続いて、tableを作成します。

todo

# 項目名 データ型(長さ) オプション
1 createdAt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
2 updatedAt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
3 id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT
4 todo text NOT NULL
CREATE TABLE `todo` (
  `createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updatedAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `id` int(11) NOT NULL,
  `todo` text COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

ALTER TABLE `todo`
  ADD PRIMARY KEY (`id`);

続いて、データを先に登録していきます。

INSERT INTO `todo` (`createdAt`, `updatedAt`, `todo`) VALUES
(current_timestamp, current_timestamp, 'BeanUtilsのマップコピーを試す'),
(current_timestamp, current_timestamp, 'BeanUtilsのResultSetコピーを試す'),
(current_timestamp, current_timestamp, 'DBUtilsなどを試す'),
(current_timestamp, current_timestamp, 'DBCPでコネクションプールを試す'),
(current_timestamp, current_timestamp, 'DBUtilsでQueryRunnerを試す');

問題

jp.pjin.tech.commons.domain.Todo.java

package jp.pjin.tech.commons.domain;

import java.sql.Timestamp;

import lombok.Data;

@Data
public class Todo {
	private Timestamp createdAt;
	private Timestamp updatedAt;
	private long id;
	private String todo;
}

jp.pjin.tech.commons.Practice016.java

package jp.pjin.tech.commons;

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

import jp.pjin.tech.commons.domain.Todo;

public class Practice016 {
	public static void main(String[] args) {
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		List<Todo> todos = new ArrayList<>();

		try {
			Class.forName("org.mariadb.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		try {
			con = DriverManager.getConnection(
					"jdbc:mariadb://localhost/tech_pjin", "root", "");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		try {
			stmt = con.createStatement();
			rs = stmt.executeQuery("select * from todo");

			while (rs.next()) {
				Todo todo = new Todo();
				todo.setCreatedAt(rs.getTimestamp("createdAt"));
				todo.setUpdatedAt(rs.getTimestamp("updatedAt"));
				todo.setId(rs.getLong("id"));
				todo.setTodo(rs.getString("todo"));
				todos.add(todo);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		if (con != null) {
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

		todos.forEach(System.out::println);
	}
}

DBへ接続し、todoテーブルの一覧をTodoクラスに入れて出力しています。

上記のコードをDBCP, DBUtilsを利用して、書き換えてください。

解答例1

DBCP用のプロパティーファイルです。
eclipseでは、src直下にファイルとして作成します。
実行時は、classesの下に入っていると見れます。
プロパティーファイルは、「#」がコメントになります。

dbcp.properties

[text] # driver のフルパスです。今回はMariaDB
driverClassName=org.mariadb.jdbc.Driver
# jdbc:[dbProductName]://[host][:port]/[データベース名] url=jdbc:mariadb://localhost/tech_pjin
username=root
password=
initialSize=30
maxActive=100
maxIdle=30
maxWait=5000
validationQuery=select CURRENT_TIMESTAMP
[/text]

jp.pjin.tech.commons.Practice016ans1.java

[java] package jp.pjin.tech.commons;

import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.ResultSetDynaClass;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.apache.commons.dbutils.DbUtils;

import jp.pjin.tech.commons.domain.Todo;

public class Practice016ans1 {
public static void main(String[] args) {
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
List<Todo> todos = new ArrayList<>();

Properties prop = new Properties();
try {
prop.load(ClassLoader.getSystemResourceAsStream("dbcp.properties"));
DataSource ds = BasicDataSourceFactory.createDataSource(prop);
con = ds.getConnection();
} catch (Exception e) {
e.printStackTrace();
}

try {
stmt = con.createStatement();
rs = stmt.executeQuery("select * from todo");
Iterator<DynaBean> itr = new ResultSetDynaClass(rs, false).iterator();
while (itr.hasNext()) {
Todo todo = new Todo();
BeanUtils.copyProperties(todo, itr.next());
todos.add(todo);

}
} catch (SQLException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(stmt);
DbUtils.closeQuietly(rs);
}
DbUtils.closeQuietly(con);

todos.forEach(System.out::println);
}
}
[/java]

ResultSetをResultSetDynaClassのコンストラクターに入れて、Iteratorを取り出しループします。
取り出した一行は、DynaBeanになります。

この際に、はまるのが、ResultSetDynaClassのコンストラクターに第二引数としてfalseを入れておきます。
そうしないと、lowerCaseで処理されるため、createdAt, updatedAtがデータとして反映されません。

テーブルの項目とオブジェクトのフィールドが全部小文字の場合はあまり気にしないのですが、単語を並べた場合に、XXX_XXX(created_at)→xxxXxx(createdAt)みたいな変換はできないので注意してください。


解答例2

DBCP用のプロパティーファイルは解答例1を参照してください。

jp.pjin.tech.commons.Practice016ans2.java

[java] package jp.pjin.tech.commons;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import jp.pjin.tech.commons.domain.Todo;

public class Practice016ans2 {
public static void main(String[] args) {
Connection con = null;
List<Todo> todos = new ArrayList<>();

Properties prop = new Properties();
try {
prop.load(ClassLoader.getSystemResourceAsStream("dbcp.properties"));
DataSource ds = BasicDataSourceFactory.createDataSource(prop);
con = ds.getConnection();
} catch (Exception e) {
e.printStackTrace();
}

try {
QueryRunner qr = new QueryRunner();
todos = qr.query(con, "select * from todo", new BeanListHandler<>(Todo.class));
} catch (SQLException e) {
e.printStackTrace();
}

DbUtils.closeQuietly(con);

todos.forEach(System.out::println);
}
}
[/java]

解答例1より短くなっていると思います。
QueryRunnerを利用した例です。
BeanListHandlerにTodo.classを入れることで、マッピングしてくれます。なんて便利。そして簡単!

apache commons

Apache Commons Javaプログラム演習問題 第23回

Apache Commons を利用した Java でのプログラム作成問題の23回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 ※この出題形式に関しては答えは1つではありません。 解答例はできるだけ複数載せるつもりですが、問題文の要件を満たしていれば正
apache commons

Apache Commons Javaプログラム演習問題 第22回

Apache Commons を利用した Java でのプログラム作成問題の22回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 ※この出題形式に関しては答えは1つではありません。 解答例はできるだけ複数載せるつもりですが、問題文の要件を満たしていれば正
apache commons

Apache Commons Javaプログラム演習問題 第21回

Apache Commons を利用した Java でのプログラム作成問題の21回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 ※この出題形式に関しては答えは1つではありません。 解答例はできるだけ複数載せるつもりですが、問題文の要件を満たしていれば正
apache commons

Apache Commons Javaプログラム演習問題 第20回

Apache Commons を利用した Java でのプログラム作成問題の20回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 ※この出題形式に関しては答えは1つではありません。 解答例はできるだけ複数載せるつもりですが、問題文の要件を満たしていれば正
apache commons

Apache Commons Javaプログラム演習問題 第19回

Apache Commons を利用した Java でのプログラム作成問題の19回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 DB環境の準備は、Apache Commons Javaプログラム演習問題 第16回をご覧ください。 ※この出題形式に関して
apache commons

Apache Commons Javaプログラム演習問題 第18回

Apache Commons を利用した Java でのプログラム作成問題の18回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 DB環境の準備は、Apache Commons Javaプログラム演習問題 第16回をご覧ください。 ※この出題形式に関して
apache commons

Apache Commons Javaプログラム演習問題 第17回

Apache Commons を利用した Java でのプログラム作成問題の17回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 DB環境の準備は、Apache Commons Javaプログラム演習問題 第16回をご覧ください。 ※この出題形式に関して
apache commons

Apache Commons Javaプログラム演習問題 第16回

Apache Commons を利用した Java でのプログラム作成問題の16回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 ※この出題形式に関しては答えは1つではありません。 解答例はできるだけ複数載せるつもりですが、問題文の要件を満たしていれば正
apache commons

Apache Commons Javaプログラム演習問題 第12回

Apache Commons を利用した Java でのプログラム作成問題の12回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 ※この出題形式に関しては答えは1つではありません。 解答例はできるだけ複数載せるつもりですが、問題文の要件を満たしていれば正
apache commons

Apache Commons Javaプログラム演習問題 第15回

Apache Commons を利用した Java でのプログラム作成問題の15回目となります。 環境を構築していない場合は、概要を読み、環境を構築してから実施してください。 ※この出題形式に関しては答えは1つではありません。 解答例はできるだけ複数載せるつもりですが、問題文の要件を満たしていれば正

新連載はじまりました!新Java基礎 連載リンク

はじめてのJAVA 連載

Recent News

Recent Tips

Tag Search