Jakarta Commonsつかいまくり(その1)

よくある話で、Excelで出来た名簿をWebアプリケーションに登録したいとな。
件数はたかだか500件前後。時間もかけていられない。
どうやったら一番労力なく、最短でできるか・・・と10秒くらい考えて、ミーハーな私は以前から使ってみたかったJakarta CommonsのDBUtilsを使用してみた。

JDBCプログラミングは。ResultSetをいちいちclose()したり、Exceptionを捉えて適切に後処理したりと何かと手間である。
DBUtilsはこの辺の一番面倒でやりたくない事を肩代わりしてくれる気の利いたやつである。
ただし、SQL文は自分で書かなくちゃならない。今時のO/RマッピングWebObjectsの様には行かない。でもフットワークが軽いので、こう言った一回きりのなるべく手間のかけたくないDBの処理なんかにはもってこいだ。
普通の人ならここでバッチ登録のSQL文を作る事を考えるでしょう。
それだと面白くも何ともないので、あえてDBUtilsをつかってみる。

まずはテーブルの1レコードを表すJavaBeansを作成。

public class Hoge {
	protected String address_1;
	protected String address_2;
	
	public String getAddress_1() {
		return address_1;
	}
	public void setAddress_1(String address_1) {
		this.address_1 = address_1;
	}

	public String getAddress_2() {
		return address_2;
	}
	public void setAddress_2(String address_2) {
		this.address_2 = address_2;
	}

}

DBのカラム名がもともとaddress_1みたいな形で、これをそのままJavaBeansにすると美しくない。まぁ、いいか。
getter、setterはEclipseが作ってくれるのでラクチン。

お次はこのJavaBeansをUpdateするSQLをかく。
Update文はJDBCのPreparedStatementを使う時のように、

UPDATE hoge_table SET address_1=?, address_2=?

の様に書く。このSQLにバインドする実際の値はObject配列で渡す事になる。
こんな感じ。

QueryRunner runner;
...
String sql="UPDATE hoge_table SET address_1=?, address_2=?";
String[] bindings={"東京都千代田区1番地1","コーポホゲホゲ101号室"}
runner.update(sql,bindings);

このQueryRunnerってやつは、読んで時の如くSQLを発行してくれるクラスで、updateメソッドが更新/削除系、queryメソッドが検索系メソッドになる。
QueryRunnerを作る時には、あらかじめDBのConnectionを張って、それをセットしてやる必要があるが、それすら面倒なので、Commons DBCPにデータソースをプーリングしてもらう事にした。

BasicDataSource bds=new BasicDataSource();
bds.setDriverClassName("org.postgresql.Driver");
...(その他お決まりのJDBC URLとかUserとかをセットしてあげる。)...
QueryRunner runner=new QueryRunner(bds);

うーん。潔くて気持ち良い。
こうなってくると、SQLを書く事すら面倒になる。
Hogeクラスの実際の項目数は15個くらいある。これをテキストでハードコーディングするのは何となくみっともない。。。
そこで登場願うのが、Commons BeanUtils。
こいつにはgetProperty()メソッドという、便利なものがある。
たとえば、Hogeクラスのaddress_1を呼び出すには当然

String address1=hoge.getAddress_1();

とすればとって来れる。しかし、BeanUtilsを使えばこうできる。

String address1=BeanUtils.getProperty(hoge,"address_1");

address_2を呼び出すには

String address2=BeanUtils.getProperty(hoge,"address_2");

とすればよい。
つまり、こうなるだろう。

String columns={"address_1","address_2"};
String values={"",""};
for (int i=0; i

これのいったい何がうれしいのかというと、DBUtilsのupdateメソッドの第二引数でObject配列を渡す時に便利になる。

public class Hoge {
	protected int id;
	protected String address_1;
	protected String address_2;
	
	protected String COLUMNS={"address_1","address_2"};
	
	public Hoge(int id) {
		this.id=id;
	}
	
	public String getAddress_1() {
		return address_1;
	}
	public void setAddress_1(String address_1) {
		this.address_1 = address_1;
	}

	public String getAddress_2() {
		return address_2;
	}
	public void setAddress_2(String address_2) {
		this.address_2 = address_2;
	}
	
	/**UPDATE文のSQLを作るメソッド*/
	public String getUpdateSQL() {
			StringBuffer strbuf = new StringBuffer("UPDATE syoka_code_table SET ");
			for (int i = 0; i < COLUMNS.length; i++) {
				strbuf.append(COLUMNS[i]);
				strbuf.append("=?");
				if (i < COLUMNS.length - 1) {
					strbuf.append(",");
				}
			}
			strbuf.append(" WHERE id=");
			strbuf.append(id);
			return strbuf.toString();
	}
	
	/**DBUtilsのupdateメソッド第二引数のためのメソッド*/
	public String getValues() {
		String[] values=new String[COLUMNS.length];
		for (int i=0; i

なんだか返ってめんどくさい事になったように見える。
しかし、メンバ変数が多い時に、COLUMNS配列を増やすだけでSQL文などいちいち書き換えなくて良くなる。
たしかにメンバ変数にaddress_1、COLUMNS配列に文字列として"address_1"とあるのはミットッモナイ。それは認める・・・
ここをすっきりさせる方法はあるが、今回はあまり突っ込まない事にして、次ぎにいく。