広告

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■
                      2010年04月21日

    Java総合講座 - 初心者から達人へのパスポート
                  2009年11月開講コース 023号

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■□■□■□■□■□■□■□■□■□■□■□■□■□■□■


-------------------------------------------------------
・現在、このメールマガジンは以下の2部構成になっています。
[1] 当初からのコース:毎週日曜の夜に発行
   これは現在、中級レベルになっています。
[2] 2009年11月開講コース:毎週水曜の夜に発行
   これは現在、初心者向けのレベルになっています。
・このメールマガジンは、画面を最大化して見てください。
小さな画面で見ていると、不適切な位置で行が切れてしまう
など、問題を起すことがあります。
・このメールマガジンに掲載されているソース・コード及び
文章は特に断らない限り、すべて筆者が著作権を所有してい
ます。また、これらのソース・コードは学習用のためだけに
提供しているものです。
-------------------------------------------------------


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
(2009年11月開講コース)023号
 当記事はvol.024のリバイバル(revival)版です。
 vol.024の内容を最新のEclipse、Javaに基づいて書き直しています。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


========================================================
◆ 01.データベース(続き)
========================================================

それでは、毎回同じようなSQL文を書かなくてもよいように別の
方法でSQL文をRDBMSに送り込むようにしてみましょう。

以下がそのプログラム例です。

---------------------------------------------------
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;

public class DbPsTest {
   public static void main(String[] args) {
      {
         try {
            Class.forName("org.h2.Driver");
            Properties props = new Properties();
            props.put("user", "sa");
            props.put("password", "");
            Connection conn = DriverManager.getConnection
            ("jdbc:h2:tcp://localhost/~/test", props);
            conn.setAutoCommit(false);
            PreparedStatement inSql = conn.prepareStatement
            ("INSERT INTO hotel  VALUES (?, ?, ?)");
            inSql.setInt(1, 13);
            inSql.setString(2, "なんとかホテル");
            inSql.setString(3, "市川市某町301-300-300");
            inSql.executeUpdate();
            inSql.setInt(1, 14);
            inSql.setString(2, "かんとかホテル");
            inSql.setString(3, "市川市某町302-300-300");
            inSql.executeUpdate();
            inSql.setInt(1, 15);
            inSql.setString(2, "某ホテル3");
            inSql.setString(3, "市川市某町303-300-300");
            inSql.executeUpdate();
            inSql.close();
            conn.commit();
            conn.close();
         }
         catch (SQLException exception) {
            exception.printStackTrace();
         }
         catch (Exception otherException) {
            otherException.printStackTrace();
         }
      }
   }
}
---------------------------------------------------

           
まず、前回のプログラム例とは20行目

PreparedStatement inSql = conn.prepareStatement("INSERT INTO hotel  VALUES (?, ?, ?)");

のところから違ってきています。
前回はStatementというのを使っていたのに対して、今回は
PreparedStatementというのを使っています。

このPreparedStatementというのは、文字通り、あらかじめ
SQL文の骨組みを準備(prepare)しておいて、あとでそれに
肉付けしてRDBMSに送り込むものです。その骨組みの部分は
ConnectionのprepareStatement()メソッドの引数に指定しま
す。
20行目の例では、その骨組みの部分は

"INSERT INTO hotel  VALUES (?, ?, ?)"

になっています。
ここには「?」が3個ついていますが、これは後で肉付けする
部分です。
前回のプログラム例を見ればわかるように、最初の「?」がホ
テルの番号、2番目の「?」がホテルの名前、3番目の「?」が
ホテルの住所を表しています。

そして、次の21〜23行目

inSql.setInt(1, 3);
inSql.setString(2, "なんとかホテル");
inSql.setString(3, "市川市某町301-300-300");

がこれらの「?」に肉付けをしているコードです。
setInt()はint型の値を先ほどの「?」の部分に設定するための
メソッドで、第一番目の引数は何番目の「?」に対するものであ
るかを表します。
つまり上の例ではPreparedStatementの1番目の「?」に3という数
を設定することを意味します。
同様にsetStringはString型の値を先ほどの「?」の部分に設定す
るためのメソッドで、第一番目の引数は何番目の「?」に対する
ものであるかを表します。

つまり上の例ではPreparedStatementの2番目の「?」に
"なんとかホテル"という文字列を設定し、3番目の「?」に
"市川市某町301-300-300"という文字列を設定することを意味
します。

PreparedStatementには上記のsetInt()やsetString()以外にも
同様のメソッドがいろいろありますが、詳細は後述。

24行目
inSql.executeUpdate();

は、PreparedStatementに対して肉付けまで行ったSQL文をRDBMS
に送り込む操作を行っています。

inSql.execute();

としても同様にSQL文をRDBMSに送り込まれます。

次の25行目〜32行目

inSql.setInt(1, 4);
inSql.setString(2, "かんとかホテル");
inSql.setString(3, "市川市某町302-300-300");
inSql.executeUpdate();
inSql.setInt(1, 5);
inSql.setString(2, "某ホテル3");
inSql.setString(3, "市川市某町303-300-300");
inSql.executeUpdate();

も同様です。

あとは前回と同じですね。

ところで、21〜32行目を見た限りでは、前回よりも簡単になった
という感じはしないかも知れません。

しかし、この部分は通常は、もっと多量のデータをforループ(後述)
やwhileループ(後述)によって処理するので、Statementを使うより
もはるかに簡単になるのです。(続く)



========================================================
◆ 02.文法解説 [演算子]
========================================================

[算術用の二項演算子 +]

二項演算子(binary operator)の前後には演算(operation)の対象
となるリテラルまたは変数名を書きますが、これらを「オペランド」
(operand)と呼びます。
たとえば、

int y = x + 10;

という文においては、xと10が演算子(+)のオペランドになります。

+演算子の前後が数を表すオペランドの場合は+は足し算(加算)を行
う演算子になります。

この加算の演算子においては、足し算をするにあたって、オペランド
の型に応じて以下の型変換が行われます。(あくまで加算の計算のため
の一時的な変換であってオペランドそのものが変わってしまうのでは
ありません。)

(1) どちらかのオペランドがdouble型であれば、他方もdoubleに変換
される。
(2) (1)に該当しない場合は、どちらかのオペランドがfloat型であれ
ば、他方もfloatに変換される。
(3) (1),(2)のどちらにも該当しない場合は、どちらかのオペランドが
longであれば他方もlongに変換される。
(4) (1),(2),(3)のどれにも該当しない場合は、両方のオペランドが
intに変換される。

以上を簡単に表現すると「(絶対値が)より大きい数を含められる型
のほうに変換される」と覚えればじゅうぶんでしょう。

そして変換されたオペランドの値に対して加算が行われ、その計算結果
が同じ型のままで算出されます。
なお、計算結果がその型の最大値を超えてしまう場合は、その型では
値が収まりきれないため、誤った計算結果になってしまいます。しかも、
このような場合でもエラーあるいは例外(Exception)が発生するわけでは
ありませんので、あらかじめ計算結果の大きさを見込んだ上でじゅうぶん
大きな値がはいる型にしておく必要があります。

なお、浮動小数点数の加算においては、この演算は一方または両方のオペ
ランドが正負の無限大の場合、および一方のオペランドがNaN
(= Not a Number = 「数ではない」の意味を短縮した用語)の場合にも
適用され、それぞれ以下のような結果となります。
(NaNは「0割る0」などの不正な演算による不定の結果を表すための値です。)

(1) どちらか一方のオペランドが無限大の場合は、結果は無限大(符号
は無限大のオペランドの符号と同じ)。
(2) 両方のオペランドが無限大でそれらの符号が同じ場合は、結果も
同じ符合の無限大。
(3) 両方のオペランドが無限大でそれらの符号が異なる場合は、結果はNaN。
(4) 両方または一方のオペランドがNaNの場合は、結果はNaN。

なお、正の無限大、負の無限大、およびNaNはFloat(float型を表現する
クラス)およびDouble(double型を表現するクラス)のそれぞれ
POSITIVE_INFINITY、NEGATIVE_INFINITY、NaNという定数
(public static finalが指定されたクラス変数)として定義されて
います。

(続く)



================================================
◆ 03.演習問題
================================================

下記のようなプログラムを作って、実行してみてください。

---------------------------------------------------------------------------------
public class ArithmeticOperationTest {

   public static void main(String[] args) {
      System.out.println("-∞ + +∞ = " + (Float.NEGATIVE_INFINITY + Float.POSITIVE_INFINITY));
      System.out.println("+∞ + -∞ = " + (Double.POSITIVE_INFINITY + Float.NEGATIVE_INFINITY));
      System.out.println("+∞ + +∞ = " + (Float.POSITIVE_INFINITY + Double.POSITIVE_INFINITY));
      System.out.println("-∞ + -∞ = " + (Float.NEGATIVE_INFINITY + Float.NEGATIVE_INFINITY));
      System.out.println("10 + NaN = " + (10 + Float.NaN));
      System.out.println("NaN + 100 = " + (Double.NaN + 100));
      System.out.println("+∞ + NaN = " + (Float.POSITIVE_INFINITY + Double.NaN));
      System.out.println("0 / 0 = " + (0.0d / 0.0));
      System.out.println("10 / 0 = " + (10.0d / 0.0));
      System.out.println("-10 / 0 = " + (-10.0d / 0.0));
   }
}
---------------------------------------------------------------------------------

結果はどうなりますか。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2010 Future Lifestyle Inc. 不許無断複製