アプリケーションからの データベースアクセス 講師: 大川 昌弘 [email protected] 更新日: 2014/12/07 1 データベースアクセス形態 典型的な例 Web ブラウザ データベース クライアント アプリケーション Web アプリケーション サーバー データベース 2 データベース クライアントアプリケーション 各データベース製品が 独自のAPIを提供 標準インターフェースに 合わせたAPIを提供 データベース クライアント アプリケーション データベース クライアント アプリケーション データベース アクセス API 標準インターフェース データベース データベース データベース アクセス API 3 各データベース製品が 独自のAPIを提供 • 例: OracleのOCI – データベース接続 • strcpy( usernames, "scott/tiger@ora" ); • rc = orlon( &lda, hda, usernames, -1, (text *)0, -1, 0 ); – SQL文を準備 • strcpy( sql, "SELECT ename, deptno INTO :ename, :dno FROM emp WHERE empno = :eno" ); • rc = oparse( &cda, sql, strlen( sql ), 1, 2 ); – 入力値のセット • eno = 1234; • rc = obndrv( &cda, ":eno", -1, (ub1 *)&eno, sizeof( int ), 3, -1, 0, 0, -1, -1 ); – SQL実行結果の値が保存される変数のセット • rc = odefin( &cda, 1, ename, 32, 96, -1, 0, 0, -1, -1, 0, 0 ); • rc = odefin( &cda, 1, dno, sizeof(int), 3, -1, 0, 0, -1, -1, 0, 0 ); – SQL文の実行 • rc = oexfet( &cda, 1, -1, -1 ); – 実行結果を1行ずつ取得(フェッチ:Fetch) • rc = ofen( &cda, 1 ); – … 4 各データベース製品が 独自のAPIを提供 • 例: SybaseのDBLIB – データベース接続 • • • • login = dblogin(); DBSETLPWD(login, "password"); DBSETAPP(login, "app"); dbproc = dbopen(login, NULL); – SQL文を準備 • dbcmd(dbproc, "select ename,deptname from emp where empno=1234"); – SQL文の実行 • dbsqlexec(dbproc); – SQL実行結果の値が保存される変数のセット • dbbind(dbproc, 1, STRINGBIND, (DBINT)0, ename); • dbbind(dbproc, 2, STRINGBIND, (DBINT)0, deptname); – レコードのフェッチ(実行結果を1行ずつ取得) • dbnextrow(dbproc); – … 5 標準インターフェース • 代表的な例 – ODBC • Open Database Connectivityの略 • マイクロソフトが1992年にC言語上のAPIレベルで統一 したインターフェイスとしてデータベースに接続するた めのAPIをまとめた • ODBC3.0が1995年に「SQL/CLI」としてSQL標準の一部と なる – JDBC • Java Database Connectivity • JDK 1.1で正式にJavaの基本SDKに同梱 6 ODBC 7 ODBC • API例 – 資源(メモリ領域)の獲得 • SQLAllocEnv(&env); • SQLAllocConnect(henv, &hdbc); – データベース接続 • SQLConnect(hdbc, server, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS); – SQL文の実行 • SQLAllocStmt(hdbc, &hstmt); • strcpy(select, "select empno, ename from emp"); • SQLExecDirect(hstmt, select, SQL_NTS); – SQL実行結果の値が保存される変数のセット • SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &id, 0, NULL); • SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, MAX_NAME_LEN, 0, name, 0, NULL); – レコードのフェッチ(実行結果を1行ずつ取得) • SQLFetch(hstmt); – … 8 ODBCの構成要素 • ODBCクライアント ODBC アプリケーション – クライアントアプリケーションの データベース要求を処理 ODBC クライアント • ODBCマネージャ – ODBCクライアントからの要求を 処理 – 各DB製品用ODBCドライバの 組み込みと処理要求 ODBC マネージャ ODBC ドライバ (DB2用) • ODBCドライバ – ODBCマネージャからの要求を 処理し、該当するDBにアクセス DB1 DB2 ODBC ドライバ (Oracle用) DB3 DB4 9 ODBCマネージャ • Windowsは標準装備 • UNIX系は、以下のようなものを導入する – UnixODBC • http://www.unixodbc.org – DataDirect • http://www.datadirect.com 10 ODBCアプリケーション • 例: – ExcelからODBC経由で各DBにアクセス可能 11 ODBCデータソースの構成 12 ODBCデータソースの構成 13 ODBCデータソースの構成 14 ExcelからODBCアクセス 15 ExcelからODBCアクセス 16 ExcelからODBCアクセス 17 ExcelからODBCアクセス 18 ExcelからODBCアクセス 19 Java (JDBCの前に) 20 Java • オブジェクト指向プログラム言語 • Java実行環境(JRE=Java Runtime Environment) – JREがあれば、コンパイルしたJavaが実行可能 • Java開発環境(JDK=Java Development Kit) – JDKがあれば、Javaのプログラムをコンパイル可能 – JREも含まれるので、コンパイルしたJavaを実行可能 Java プログラム 基本的にどこでも実行可能 Windows用JRE Linux用JRE Solaris用JRE AIX用JRE Windows Linux Solaris AIX 21 Javaのプログラム例 public class Hello { public static void main(String[] args) { System.out.println("クラスオブジェクトの作成"); Hello hello = new Hello(); System.out.println("メソッドの呼び出し1"); hello.sayHello(); System.out.println("メソッドの呼び出し2"); String s = hello.getMessage("日本"); System.out.println("メソッドの呼び出し2で受け取ったメッセージ: " + s); } public Hello() { System.out.println("コンストラクター"); } public void sayHello() { System.out.println("ハロー"); } public String getMessage(String s) { Javaソースファイルの拡張子は、.java String s2 = "ようこそ" + s; 例えば Hello.java return s2; } } 22 Javaのコンパイル • javac [Javaファイル名] – 前ページのファイル名を Hello.java とすると、 > javac Hello.java – 結果としてコンパイルされたファイル Hello.class が生成される 23 Javaの実行 • java [クラス名] – 前ページの Hello.class を実行する場合、 > java Hello クラスオブジェクトの作成 コンストラクター メソッドの呼び出し1 ハロー メソッドの呼び出し2 メソッドの呼び出し2で受け取ったメッセージ: ようこそ日本 24 Javaのパッケージ化 • Javaが複数のパッケージから構成される場合、それらを1つにまとめるこ とができる • 拡張子をjarとする。そのためjarファイルと呼ばれる • pkgディレクトリ下のすべてのファイルをまとめて、pkg.jarファイルを作成 する場合 > jar cvf pkg.jar pkg/ マニフェストが追加されました 追加中: pkg/(入力 = 0) (出力 = 0)(保管済み: 0%) 追加中: pkg/a.class(入力 = 4) (出力 = 6)(圧縮率 -50%) 追加中: pkg/b.class(入力 = 4) (出力 = 6)(圧縮率 -50%) • 既存のディレクトリにある*.classファイルをまとめて、hello.jarファイルを作 成する場合 > jar cvf hello.jar *.class マニフェストが追加されました 追加中: Hello.class(入力 = 1102) (出力 = 665)(圧縮率 39%) 25 jarファイルにあるクラスの実行 • java -classpath [jarファイル名] [クラス名] > java -classpath hello.jar Hello クラスオブジェクトの作成 コンストラクター メソッドの呼び出し1 ハロー メソッドの呼び出し2 メソッドの呼び出し2で受け取ったメッセージ: ようこそ日本 • あるいは CLASSPATH 環境変数にjarファイルをセット > set CLASSPATH=hello.jar > java Hello クラスオブジェクトの作成 コンストラクター メソッドの呼び出し1 ハロー メソッドの呼び出し2 メソッドの呼び出し2で受け取ったメッセージ: ようこそ日本 26 eclipseによる開発 27 eclipseによる開発(デバッグ画面) 28 JDBC 29 JDBC • JDBCライブラリを使用して プログラミングする • プログラミングで使用する JDBCドライバのクラスを 動的にロードする • JDBCライブラリはJREやJDKに 同梱 JDBC アプリケーション1 JDBC アプリケーション2 JDBCライブラリ JDBCライブラリ JDBCドライバ (DB2用) JDBCドライバ (Oracle用) データベース管理 システム (DB2) データベース管理 システム (Oracle) • JDBCドライバは一般的に 各DB製品に同梱 DB1 DB2 DB3 DB4 30 JDBCドライバのタイプ • タイプ1,2,3,4があるが、2と4が多い。4が主流 • タイプ2 – JDBCからの要求を、OS専用のDBライブラリを用いて 処理する – TCP/IPを経由せず、直接DBにアクセスすることも可能 – OSに依存 • タイプ4 – JDBCからの要求を、すべてJava上で処理する – 一般的にTCP/IPを経由 – OSに依存しない 31 JDBCプログラミング例 JDBCSample1.java (1/2) import java.sql.*; public class JDBCSample1 { DB2のJDBCドライバ・クラスをロード public static void main(String[] args) { String pubname; String title; データベースに接続 try { Class.forName("com.ibm.db2.jcc.DB2Driver"); Connection conn = DriverManager.getConnection("jdbc:db2://localhost:50000/shonanit", "userid", "password"); conn.setAutoCommit(false); SQL文を実行 Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select pubname,title from publisher,book where publisher.pid=book.pid"); while (rs.next()) { SQL文の実行結果を1行ずつ取得 pubname = rs.getString(1); title = rs.getString(2); System.out.println(pubname + ", " + title); } 32 JDBCプログラミング例 JDBCSample1.java (1/2) rs.close(); stmt.close(); conn.commit(); conn.close(); } catch (Exception e) { System.out.println("Exception : " + e.toString()); e.printStackTrace(); } } } 33 Javaのコンパイル • javac [Javaファイル名] – 前ページのファイル名を Hello.java とすると、 > javac JDBCSample1.java – 結果としてコンパイルされたファイル JDBCSample1.class が生成される 34 Javaの実行 • 実行すると以下のエラー >java JDBCSample1 Exception : java.lang.ClassNotFoundException: com.ibm.db2.jcc.DB2Driver java.lang.ClassNotFoundException: com.ibm.db2.jcc.DB2Driver at java.lang.Class.forName(Class.java:137) at JDBCSample1.main(JDBCSample1.java:8) – これは、DB2のJDBCドライバ・クラスが見つからな いため – DB2のJDBCドライバ・クラス • [DB2導入ディレクトリ]¥SQLLIB¥java¥db2jcc4.jar 35 Javaの実行 • DB2のJDBCドライバ・クラス・ファイルをCLASSPATH環境変数にセット して実行 – JDBCSample1.classがカレントディレクトリにあるので、;. も加える >set CLASSPATH=[DB2導入ディレクトリ]/SQLLIB/java/db2jcc4.jar;. >java JDBCSample1 小学館, はみだしインディアンのホントにホントの物語 講談社, フュージョン 岩波書店, ナルニア国物語 岩波書店, ホビットの冒険 講談社, 穴 毎日新聞社, 14歳の君へ 早川書房, これからの「正義」の話をしよう 36 SELECT文の条件(定数との比較方法) SQL文に直接書くやり方 Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select bid,title from book where bid=3"); while (rs.next()) { bid = rs.getString(1); title = rs.getString(2); BID列のデータ・タイプはINTEGERだが System.out.println(bid + ", " + title); Stringで受けることも可能 } (自動変換してくれる) BID列の値をint型で受ける場合 int bid2; … Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select bid,title from book where bid=3"); while (rs.next()) { bid2 = rs.getInt(1); title = rs.getString(2); System.out.println(bid2 + ", " + title); } 37 SELECT文の条件(定数との比較方法) SQL文には値の代わりに ? を使用し、値は後でセットする(?をパラメーター・マーカーと呼ぶ) PreparedStatement pstmt = conn.prepareStatement("select bid,title from book where bid=?"); pstmt.setInt(1, 3); 1つ目の?に3をセットする ResultSet rs = pstmt.executeQuery(); while (rs.next()) { bid = rs.getString(1); title = rs.getString(2); System.out.println(bid + ", " + title); } pstmt.setInt(1, 6); rs = pstmt.executeQuery(); … この方法だと値が異なる場合でも、同じSQL文を使いまわすことができる • conn.prepareStatementメソッドの実行で、アクセス・プランが生成される o アクセス・プラン … SQL文をどのように処理するかを示したもの • 1回のアクセス・プラン生成で、複数回のSQL文を実行することができる 38 挿入・更新等(レコードが戻らないSQL) パラメーター・マーカーを使用する場合 PreparedStatement pstmt = conn.prepareStatement("insert into publisher values (?,?)"); pstmt.setInt(1, 6); pstmt.setString(2, "日本経済新聞社"); pstmt.execute(); pstmt.close(); パラメーター・マーカーを使用しない場合 Statement stmt = conn.createStatement(); stmt.execute("delete from publisher where pubname='日本経済新聞社'"); stmt.close(); 39 END 40
© Copyright 2026 Paperzz