広告

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■
                      2010年05月05日

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

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


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


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


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

今回は、PreparedStatementを使ってUPDATE(更新)を行うSQL文を
実行してみましょう。

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

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

public class DbTest4 {
   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("UPDATE hotel SET address = ? WHERE num = ?");
            inSql.setString(1, "市川市某町301-300-300");
            inSql.setInt(2, 2);
            inSql.executeUpdate();
            inSql.close();
            conn.commit();
            conn.close();
         }
         catch (SQLException exception) {
            exception.printStackTrace();
         }
         catch (Exception otherException) {
            otherException.printStackTrace();
         }
      }
   }
}
---------------------------------------------------
           
前々回(vol.024)と同じようなパターンですね。

SQLのINSERT文がUPDATE文に代わったことを除けば、前々回の
説明を読めば内容は理解できるでしょう。

というわけで、今回はこれで終わり!





・・・と言ったら、短すぎますね。


一応、簡単に説明しておきましょう。

20行目

PreparedStatement inSql = conn.prepareStatement("UPDATE hotel SET address = ? WHERE num = ?");

は、UPDATEを行うためのSQL文の骨組みを作っているところですね。

このプログラムでは最終的には、

UPDATE hotel SET address = '市川市某町301-300-300' WHERE num = 2

というSQL文にするのですが、addressの部分とnumの部分を可変部分
として「?」にしておき、その「?」の部分を、21行目

inSql.setString(1, "市川市某町301-300-300");

や22行目

inSql.setInt(2, 2);

で、肉付けすることによって、SQL文を完成します。

setString()メソッドやsetInt()メソッドについては前々回の説明を
読めば理解できますね。


そして23行目

inSql.executeUpdate();

によってこのSQL文を実行(RDBMSに送り込む)しています。

完成されたSQL文

UPDATE hotel SET address = '市川市某町301-300-300' WHERE num = 2

は、「hotelというテーブルの中でnumというカラムの値が2になって
いる行を見つけ、その行の中のaddressというカラムの値を「市川市
某町301-300-300」に変更する」という更新作業を行うものですね。

では、このプログラムを実際にEclipseに入力してみましょう。

プログラムを実行する前に、あらかじめH2 Consoleを起動して、
SELECT * FROM HOTELなどのSQL文を実行してhotelテーブルの中身
を確認しておきましょう。

そして、プログラムを実行し、その後、再度H2 Consoleでhotelテーブル
の中身をSELECT文で検索して、正しい更新が行われていることを確認し
ましょう。



ところで、これまでは話を簡単にするためにhotelという単一のテーブル
だけを使って説明してきましたが、通常のシステムにおいては、複数の
テーブルがお互いに関係し合いながら使用されるのが普通です。

というわけで、これから、お互いに関係する複数のテーブルの取り扱い
についてお話していきましょう。

(続く)



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

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

/演算子は割り算(除算)を行う演算子です。

たとえば、

int  x  =  20;
int  y  =  10;
int  z  =  x  /  y;

を実行すると、xの値がyの値で割られてその結果がzに代入されます。
つまりzの値は2になります。

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

(1) どちらかのオペランドがdouble型であれば、他方もdoubleに変換
される。

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

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

(4) (1),(2),(3)のどれにも該当しない場合は、両方のオペランドがint
に変換される。

以上を簡単に表現すると「(絶対値が)より大きい数を含められる型の
ほうに変換される」と覚えればじゅうぶんでしょう。
(この型変換はこれまで説明してきた+, -, *の各演算子ともに同様です。)


そして変換されたオペランドの値に対して割り算が行われ、その計算結果
が同じ型のままで算出されます。

なお、オペランドがともに整数型の場合は、割り算の結果も整数になりま
すので、結果の小数点以下は削除されます。


また、整数型の割り算の場合は割られる数が負の最小値(絶対値が最大値)
だと、-1で割っても符号が変わりません。

たとえば、

int  x  =  -2147483648;  // これはint型が取りえる最小値
int  y  =  -1;
int  z  =  x  /  y;

とすると、zには-2147483648の値がはいってしまい、+2147483648にはなり
ません。(数学的には+2147483648にならないといけませんね。念のため。)

これは要するに、取りえる負の最小値を使っては、いけないということです。

しかもこの場合でも例外(Exception)は発生しませんので注意しましょう。


同様に、前回述べた、乗算の結果が型の取りえる最大値からあふれる(型の
取りえる最大値より大きくなってしまう)ことなどはもっと頻繁におこる
可能性があり、おこっても例外もなにも発生しないために気づきにくいもの
ですので、じゅうぶんに注意しましょう。

このように、算術計算においては、型が扱えるギリギリの値や型からあふれ
る値が発生することのないように、じゅうぶん余裕を持って値を入れられる
型を使うように、日ごろから意識しておく必要があります。


一方、整数型の0で割り算すると(数学で学んだように本来0で割ってはなら
ないので)ArithmeticExceptionという例外が発生します。この場合は、例外
が発生しますので、エラーに気が付きますが、前もって、try {} catch {}を
使って例外処理を行っておくべきものです。


なお、浮動小数点数の割り算においては、この演算は一方または両方のオペラ
ンドが正負の無限大やNaNの場合にも適用され、それぞれ以下のような結果と
なります。

(1) 両方または一方のオペランドがNaNの場合は、結果はNaN。

(2) 両方のオペランドが無限大の場合は、結果はNaN。

(3) 無限大を0以外の数で割る場合の結果は無限大で、その符号は通常の数の
割り算のときと同じ(負/負は正、正/正は正、負/正は負、正/負は負)。

(4) 0を0で割る場合の結果はNaN。(浮動小数点数の0は厳密な0ではなく、
ほぼ0というい0の近似値を意味しますので注意してください。したがって、
浮動小数点数の0で割ってもエラーにはなりません。)

(5) 0を0以外の数で割る場合の結果は0で、その符号は通常の数の割り算の
ときと同じ(負/負は正、正/正は正、負/正は負、正/負は負)。(浮動小数
点数の0は完全な0ではなく0の近似値にすぎないので符号がつきます。)

また、通常の浮動小数点数の割り算においても、割り算の結果がその浮動
小数点数の型の取りえる最大値を超える場合には結果は無限大になります。
この場合の無限大の符号も通常の割り算の結果の符号と同じです。

(続く)



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

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

---------------------------------------------------------------------------------
public class ArithmeticOperationTest3 {

   public static void main(String[] args) {
      System.out.println("NaN / 5 = " + (Float.NaN / 5));
      System.out.println("NaN / NaN = " + (Float.NaN / Double.NaN));
      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("6 / -∞ = " + (6 / Float.NEGATIVE_INFINITY));
      System.out.println("-7 / -∞ = " + (-7 / Float.NEGATIVE_INFINITY));
      System.out.println("-8 / +∞ = " + (-8 / Double.POSITIVE_INFINITY));
      System.out.println("+9 / +∞ = " + (+9 / Double.POSITIVE_INFINITY));
      System.out.println("0.0 / -0.0 = " + (0.0 / -0.0));
      System.out.println("-0.0 / +0.0 = " + (-0.0 / +0.0));
      System.out.println("-0.0 / -0.0 = " + (-0.0 / -0.0d));
      System.out.println("0.0 / +0.0 = " + (0.0 / +0.0d));
      System.out.println("10 / 0.0 = " + (10 / 0.0));
      System.out.println("-11 / 0.0 = " + (-11 / 0.0));
      System.out.println("12 / -0.0 = " + (12 / -0.0d));
      System.out.println("-13 / -0.0 = " + (-13 / -0.0));
      int  x  =  Integer.MIN_VALUE;  // これはint型が取りえる最小値
      int  y  =  -1;
      int  z  =  x  /  y;
      System.out.println(x + " / " + y + " = " + z + " : 符号に注意!");
   }
}
---------------------------------------------------------------------------------

結果はどうなりますか。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      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. 不許無断複製