安易なnull
- 2016.06.24
- 新入社員研修
株式会社シンメトリック新入社員の青木です。前々回にまだ1ヶ月も製作期間があると書いたばかりなのですがその1ヶ月が短くなってまいりました。そろそろこのオセロを仕上げる段階でありたいのですが、製作しているうちにいろいろ要素を追加していきたくなってしまうので、どのようになれば仕上げかというところを決めるのが難しいです。まあ今回は要件の一つであるプロセス機能について書いていきます。
今週の目標
前回は対戦をそれぞれ記録するためにサーバーアプリケーションかデータベース接続してINSERTすることをしました。具体的には、オセロ対戦中に一手動くたびにその対戦の識別番号・そのターン数・x座標・y座標をデータベースに記録する機能をつけました。
今回はその記録したデータを活用することをします。ここでいう活用とはプロセス機能として使うことです。対戦の識別番号を入れれば、その対戦を再現できる機能をつくります。
行ったアプローチ
ブラウザ側のjavascriptで新規に追加するものとしては、番号を入力したらそれがサーバーに送られ、その後送り返されてくる番号に紐づいた対戦のプロセスを一時記憶するぐらいの機能です。座標さえ与えられていれば普通の対戦で使っている機能を使いまわせば簡単に作れそうですので詳細は割愛します。
それではサーバーでのJAVAアプリケーションで難しいことをするのかといえばそうでもなさそうです。データベース接続してSQL文を発行するという流れは前回と同じです。今回違うのはは、その用いるSQL文がデータの追加のためのINSERT文ではなく、取得のためのSELECT文を用いる程度の違いです。
その用いるSELECT文はこのようなものです。
SELECT * FROM テーブル名 WHERE ROOMID = 番号 ORDER BY TURN
テーブル内から指定の番号の対戦だけターンが若い順に取得するというみたいな意味です。
JAVAでデータベースから情報を得る際には、取得した表を一行だけ参照して情報を得たのちに次の一行へ移動して同様の処理をにするを繰り返しているみたいなのでターンの順番通りに並べています。
ところで前回のINSERT文のパターンでは、ただSQL文を実行するだけでしたのでこちらを使いました。
executeUpdate(String sql)
今回は、実行したうえで返ってくるデータがほしいのでこちらを使います。
executeQuery(String sql)
ということで以下のように書いてみました。
String table = ~;
List = new ArrayList;
Connection conn =~;
public void onMessage(String message, Session sessionSender) throws IOException {
/*messageから指定の番号(=numberとする)を得る処理*/
/*JDBCドライバの登録とデータベース接続の処理*/
//SQL文の実行
String sql = “SELECT * FROM “+ table + “ WHERE ROOMID = “ + number + ” ORDER BY TURN”;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()){
/*ArrayListにDBから得た”x,y”をターンの順どおりに入れる処理*/
}
/*Connection等のclose処理*/
/*ArrayListの中身をsessionSenderに送り返す処理*/
}
作業結果
これで一応動くのですが、ブラウザからの指定の番号を条件としてテーブル内検索してそのデータが存在しなかった場合に、ブラウザに送り返すときに何も送り返すものがなくてエラーが出てしまうようです。ですので、ResultSetに何もない場合の処理を分けて用意する必要がありました。
何もないときを返すということで、if(! (rs.equals(null )))のようにして処理を分けてみようとしたところ、これでもエラーでした。
調べてみると、ResultSetを生成した直後は参照している行がいわゆる0行目を指していて、.next()をすることですることで次の行があればtrueを返してその行へ移動、なければfalseを返すといった処理をしているようです。また、このResultSet自体はnullになることもないので、このような場合分けをするには.next()自体でtrueかfalseの判定するのがセオリーとのことでした。
ということで中にif文を差し込んでみたのが以下のものになります。
String table = ~;
List = new ArrayList;
Connection conn =~;
public void onMessage(String message, Session sessionSender) throws IOException {
/*messageから指定の番号(=numberとする)を得る処理*/
/*JDBCドライバの登録とデータベース接続の処理*/
//SQL文の実行
String sql = “SELECT * FROM “+ table + “ WHERE ROOMID = “ + number + ” ORDER BY TURN”;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()){
do{
/*ArrayListにデータベースから得た”x,y”をターンの順どおりに入れる処理*/
}while (rs.next());
}
else{
/*データベースに番号のデータがなかったときの処理*/
}
/*Connection等のclose処理*/
/*ArrayListの中身、もしくは何もなかったことをsessionSenderに送り返す処理*/
}
ifの条件式の中で既にカーソルが1行移動しているので、ループさせるのには最初に1回は読み込むためにdowhile文を用いました。
課題
前回と今回のようなやり方でデータベースの情報の処理の仕方がわかってきたので、プロセス機能と同様にデータベースの操作の機能であるランキング機能も作れました。ですので要件としては満たされたことにはなるのですが、ゲームとして見た目が洗練されていないといった問題があります。いまだに4月に作ったCSSを使いまわしているので、これを適切な見た目になるように作り変える必要があります。