テーブル定義とSQLのテスト実行が終わったら,次は Java の DSO, DAO クラスの演習を行う.
要点: DSO は,セッター,ゲッターの集まりなので,テーブル定義が決まれば,それで決まり. DAO の方は,データベースの使い方次第(ビジネスロジック)で,メソッドが増えていくが,とりあえず,このWebページに掲載のもので練習する.
この DataSourceFactory.java は PostgreSQL で動くが、 MySQL や JavaDB や HiRDB を使う場合は,先頭部分を書き換え るだけで簡単に動く。(基本は,コメントアウトの調整)
package hoge.hoge.com; public class 投稿者Dso { private Integer 投稿者ID; private String 名前表記; private String 漢字姓; private String かな姓; private String 漢字名; private String かな名; private String 性別; private String 住所; private Integer 年齢; private String 電話番号; public Integer get投稿者ID() { return this.投稿者ID; } public void set投稿者ID(Integer value) { this.投稿者ID = value; } public String get名前表記() { return this.名前表記; } public void set名前表記(String value) { this.名前表記 = value; } public String get漢字姓() { return this.漢字姓; } public void set漢字姓(String value) { this.漢字姓 = value; } public String getかな姓() { return this.かな姓; } public void setかな姓(String value) { this.かな姓 = value; } public String get漢字名() { return this.漢字名; } public void set漢字名(String value) { this.漢字名 = value; } public String getかな名() { return this.かな名; } public void setかな名(String value) { this.かな名 = value; } public String get性別() { return this.性別; } public void set性別(String value) { this.性別 = value; } public String get住所() { return this.住所; } public void set住所(String value) { this.住所 = value; } public Integer get年齢() { return this.年齢; } public void set年齢(Integer value) { this.年齢 = value; } public String get電話番号() { return this.電話番号; } public void set電話番号(String value) { this.電話番号 = value; } }
package hoge.hoge.com; public class 作品評価Dso { private Integer 投稿者ID; private String 作成日; private String タイトル; private String 著者名; private String 発行所; private String 版; private String 評価; private String 感想; public Integer get投稿者ID() { return this.投稿者ID; } public void set投稿者ID(Integer value) { this.投稿者ID = value; } public String get作成日() { return this.作成日; } public void set作成日(String value) { this.作成日 = value; } public String getタイトル() { return this.タイトル; } public void setタイトル(String value) { this.タイトル = value; } public String get著者名() { return this.著者名; } public void set著者名(String value) { this.著者名 = value; } public String get発行所() { return this.発行所; } public void set発行所(String value) { this.発行所 = value; } public String get版() { return this.版; } public void set版(String value) { this.版 = value; } public String get評価() { return this.評価; } public void set評価(String value) { this.評価 = value; } public String get感想() { return this.感想; } public void set感想(String value) { this.感想 = value; } }
package hoge.hoge.com; public class ファイルDso { private String ファイル名; private Integer 投稿者ID; public String getファイル名() { return this.ファイル名; } public void setファイル名(String value) { this.ファイル名 = value; } public Integer get投稿者ID() { return this.投稿者ID; } public void set投稿者ID(Integer value) { this.投稿者ID = value; } }
データの更新・挿入時には,null チェック,データサイズのチェック,日付のフォーマットチェック等を行うという方針です.
package hoge.hoge.com; import java.sql.*; import java.util.Calendar; import java.util.Iterator; import java.util.List; import java.util.Map; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import java.sql.Date; public class 評価データDao { // 使用するテーブル名 final private static String TABLE = "投稿者"; final private static String TABLE2 = "作品評価"; final private static String TABLE3 = "ファイル"; // private で SimpleJdbcTemplate オブジェクトを定義して、他のメソッドで使う、というのが決まり文句(詳しくは Spring のマニュアル) private SimpleJdbcTemplate jdbcTemplate; public void setDataSource(org.springframework.jdbc.datasource.DriverManagerDataSource dataSource) { this.jdbcTemplate = new SimpleJdbcTemplate(dataSource); } // // テーブル削除 // public void drop投稿者() {this.jdbcTemplate.update("drop table " + TABLE);} public void drop作品評価() {this.jdbcTemplate.update("drop table " + TABLE2);} public void dropファイル() {this.jdbcTemplate.update("drop table " + TABLE3);} // // テーブル定義 // public void create投稿者() { this.jdbcTemplate.update( "create table " + TABLE + " (" + "投稿者ID integer primary key," + "名前表記 CHAR(32) not null," + "漢字姓 CHAR(32) not null," + "かな姓 CHAR(32)," + "漢字名 CHAR(32) not null," + "かな名 CHAR(32)," + "性別 CHAR(1)," + "住所 VARCHAR(256)," + "年齢 integer," + "電話番号 CHAR(16)" + ")" ); } public void create作品評価() { this.jdbcTemplate.update("create table " + TABLE2 + " (" + "投稿者ID INTEGER not null REFERENCES 投稿者(投稿者ID)," + "作成日 DATE not null," + "タイトル VARCHAR(128) not null," + "著者名 VARCHAR(128)," + "発行所 VARCHAR(128)," + "版 CHAR(16)," + "評価 CHAR(8) not null," + "感想 VARCHAR(20000)" + ")" ); } public void createファイル() { this.jdbcTemplate.update("create table " + TABLE3 + " (" + "ファイル名 VARCHAR(200) PRIMARY KEY," + "投稿者ID INTEGER not null REFERENCES 投稿者(投稿者ID)" + ")" ); } // // 1行挿入 // public void insert評価投稿(投稿者Dso 投稿者Dso, List<作品評価Dso> 作品評価Dsoリスト, ファイルDso ファイルDso) { 作品評価Dso 作品評価DsoTemp; this.insert投稿者(投稿者Dso.get投稿者ID(),投稿者Dso.get名前表記(),投稿者Dso.get漢字姓(),投稿者Dso.getかな姓(),投稿者Dso.get漢字名(),投稿者Dso.getかな名(),投稿者Dso.get性別(),投稿者Dso.get住所(), 投稿者Dso.get年齢(),投稿者Dso.get電話番号()); Iterator<作品評価Dso> iterator = 作品評価Dsoリスト.iterator(); while(iterator.hasNext()){ 作品評価DsoTemp = iterator.next(); this.insert作品評価(作品評価DsoTemp.get投稿者ID(),作品評価DsoTemp.get作成日(),作品評価DsoTemp.getタイトル(),作品評価DsoTemp.get著者名(),作品評価DsoTemp.get発行所(),作品評価DsoTemp.get版(),作品評価DsoTemp.get評価(),作品評価DsoTemp.get感想()); } this.insertファイル(ファイルDso.getファイル名(),ファイルDso.get投稿者ID()); } // // 1行挿入 // public void insert投稿者(Integer 投稿者ID, String 名前表記, String 漢字姓, String かな姓, String 漢字名, String かな名, String 性別, String 住所, Integer 年齢, String 電話番号) { //nullチェック if(投稿者ID==null){System.out.println("insert投稿者エラー:投稿者IDは非nullでなければいけません。値を入れてください。");return;} if(名前表記==null){System.out.println("insert投稿者エラー:名前表記は非nullでなければいけません。値を入れてください。");return;} else 名前表記 = "'"+名前表記+"'"; if(漢字姓==null){System.out.println("insert投稿者エラー:漢字姓は非nullでなければいけません。値を入れてください。");return;} else 漢字姓 = "'"+漢字姓+"'"; if(漢字名==null){System.out.println("insert投稿者エラー:漢字名は非nullでなければいけません。値を入れてください。");return;} else 漢字名 = "'"+漢字名+"'"; //文字列のサイズチェック if(名前表記.getBytes().length>32){System.out.println("insert投稿者エラー:名前表記が32バイトを超えています。文字数を減らしてください。");return;} if(漢字姓.getBytes().length>32){ System.out.println("insert投稿者エラー:漢字姓が32バイトを超えています。文字数を減らしてください。");return;} if(かな姓!=null){ if(かな姓.getBytes().length>32){ System.out.println("insert投稿者エラー:かな姓が32バイトを超えています。文字数を減らしてください。");return;} else かな姓 = "'"+かな姓+"'"; } if(漢字名.getBytes().length>32){ System.out.println("insert投稿者エラー:漢字名が32バイトを超えています。文字数を減らしてください。");return;} if(かな姓!=null){ if(かな名.getBytes().length>32){System.out.println("insert投稿者エラー:かな名が32バイトを超えています。文字数を減らしてください。");return;} else かな名 = "'"+かな名+"'"; } if(性別!=null){ if(性別.getBytes().length>1){System.out.println("insert投稿者エラー:性別が1バイトを超えています。文字数を減らしてください。");return;} else 性別 = "'"+性別+"'"; } if(住所!=null){ if(住所.getBytes().length>256){System.out.println("insert投稿者エラー:住所が256バイトを超えています。文字数を減らしてください。");return;} else 住所 = "'"+住所+"'"; } if(電話番号!=null){ if(電話番号.getBytes().length>16){System.out.println("insert投稿者エラー:電話番号が16バイトを超えています。文字数を減らしてください。");return;} else 電話番号 = "'"+電話番号+"'"; } //投稿者IDの重複チェック if(this.jdbcTemplate.queryForInt("select count(*) from " + TABLE + " where 投稿者ID = ?", 投稿者ID)>1){System.out.println("与えられた投稿者ID("+ 投稿者ID + ")は既に登録されている。");return;} this.jdbcTemplate.update("insert into " + TABLE + " values ( " + 投稿者ID + ", " + 名前表記 + ", " + 漢字姓 + ", " + かな姓 + ", " + 漢字名 + ", " + かな名 + ", " + 性別 + ", " + 住所 + ", " + 年齢 + ", " + 電話番号 + " )"); } public void insert作品評価(Integer 投稿者ID, String 作成日, String タイトル, String 著者名, String 発行所, String 版, String 評価, String 感想) { try{ //作成日のフォーマットチェック Calendar c = Calendar.getInstance(); Date date_format = new Date(c.getTimeInMillis()); date_format = Date.valueOf(作成日); if(作成日.compareTo(date_format.toString())!=0){System.out.println( "insert作品評価エラー:作成日が正しくありません。" );return;} //nullチェック if(投稿者ID==null){System.out.println("insert作品評価エラー:投稿者IDは非nullでなければいけません。値を入れてください。");return;} if(作成日==null){System.out.println("insert作品評価エラー:作成日は非nullでなければいけません。値を入れてください。");return;} else 作成日 = "'"+作成日+"'"; if(タイトル==null){System.out.println("insert作品評価エラー:タイトルは非nullでなければいけません。値を入れてください。");return;} else タイトル = "'"+タイトル+"'"; if(評価==null){System.out.println("insert作品評価エラー:評価は非nullでなければいけません。値を入れてください。");return;} else 評価 = "'"+評価+"'"; //文字列のサイズチェック if(タイトル.getBytes().length>128){System.out.println("insert作品評価エラー:タイトルが128バイトを超えています。文字数を減らしてください。");return;} if(著者名!=null){ if(著者名.getBytes().length>128){System.out.println("insert作品評価エラー:著者名が128バイトを超えています。文字数を減らしてください。");return;} else 著者名 = "'"+著者名+"'"; } if(発行所!=null){ if(発行所.getBytes().length>128){System.out.println("insert作品評価エラー:発行所が128バイトを超えています。文字数を減らしてください。");return;} else 発行所 = "'"+発行所+"'"; } if(版!=null){ if(版.getBytes().length>16){System.out.println("insert作品評価エラー:版が16バイトを超えています。文字数を減らしてください。");return;} else 版 = "'"+版+"'"; } if(評価.getBytes().length>8){System.out.println("insert作品評価エラー:評価が8バイトを超えています。文字数を減らしてください。");return;} if(感想!=null){ if(感想.getBytes().length>20000){System.out.println("insert作品評価エラー:感想が20000バイトを超えています。文字数を減らしてください。");return;} else 感想 = "'"+感想+"'"; } this.jdbcTemplate.update("insert into " + TABLE2 + " values ( " + 投稿者ID + ", " + 作成日 + ", " + タイトル + ", " + 著者名 + ", " + 発行所 + ", " + 版 + ", " + 評価 + ", " + 感想 + " )"); } catch(java.lang.IllegalArgumentException e){ System.out.println( "insert作品評価エラー:作成日のフォーマットが正しくありません。正しいフォーマット:yyyy-mm-dd" ); } } public void insertファイル(String ファイル名, Integer 投稿者ID) { //nullチェック if(ファイル名==null){System.out.println("insertファイルエラー:ファイル名は非nullでなければいけません。値を入れてください。");return;} else ファイル名 = "'"+ファイル名+"'"; if(投稿者ID==null){System.out.println("insertファイルエラー:投稿者IDは非nullでなければいけません。値を入れてください。");return;} //文字列のサイズチェック if(ファイル名.getBytes().length>256){System.out.println("insertファイルエラー:ファイル名が256バイトを超えています。文字数を減らしてください。");return;} this.jdbcTemplate.update("insert into " + TABLE3 + " values ( " + ファイル名 + ", " + 投稿者ID + " )"); } // // 値の更新 // public void set漢字姓(Integer 投稿者ID, String 漢字姓) {this.jdbcTemplate.update("update " + TABLE + " set 漢字姓 = ? where 投稿者ID = ?", new Object[] {漢字姓, new Integer(投稿者ID)});} // // 問い合わせ // // タップル数 public int getCount投稿者() {return this.jdbcTemplate.queryForInt("select count(*) from " + TABLE);} public int getCount作品評価() {return this.jdbcTemplate.queryForInt("select count(*) from " + TABLE2);} public int getCountファイル() {return this.jdbcTemplate.queryForInt("select count(*) from " + TABLE3);} // 選択条件の無い4つの問い合わせ // 1.結果が、単純値(漢字姓,漢字名)のリスト public List<Map<String,Object>> getAll漢字氏名() {return this.jdbcTemplate.queryForList("select 漢字姓,漢字名 from " + TABLE);} // 2.結果が、単純値(投稿者ID)のリスト public List<Map<String,Object>> getAll投稿者ID() {return this.jdbcTemplate.queryForList("select 投稿者ID from " + TABLE);} // 3.結果がタップルのリスト public List<Map<String,Object>> getAll投稿者() {return this.jdbcTemplate.queryForList("select * from " + TABLE);} public List<Map<String,Object>> getAll作品評価() {return this.jdbcTemplate.queryForList("select * from " + TABLE2);} public List<Map<String,Object>> getAllファイル() {return this.jdbcTemplate.queryForList("select * from " + TABLE3);} // 4.結果が、投稿者Dso オブジェクトのリスト (つまり、結果が Java の 投稿者Dso オブジェクトに格納されている) public List<投稿者Dso> getAll投稿者Dso() { return this.jdbcTemplate.query( "select * from " + TABLE, new org.springframework.jdbc.core.simple.ParameterizedRowMapper<投稿者Dso>() { public 投稿者Dso mapRow(ResultSet rs, int rowNum) throws SQLException { 投稿者Dso p = new 投稿者Dso(); p.set投稿者ID(rs.getInt("投稿者ID")); p.set名前表記(rs.getString("名前表記")); p.set漢字姓(rs.getString("漢字姓")); p.setかな姓(rs.getString("かな姓")); p.set漢字名(rs.getString("漢字名")); p.setかな名(rs.getString("かな名")); p.set性別(rs.getString("性別")); p.set住所(rs.getString("住所")); p.set年齢(rs.getInt("年齢")); p.set電話番号(rs.getString("電話番号")); return p; } }); } // 選択条件あり.投稿者ID で選択したときのタップル数 public int 投稿者getCountBy投稿者ID( Integer 投稿者ID ) {return this.jdbcTemplate.queryForInt("select count(*) from " + TABLE + " where 投稿者ID = ?", 投稿者ID);} public int 作品評価getCountBy投稿者ID( Integer 投稿者ID ) {return this.jdbcTemplate.queryForInt("select count(*) from " + TABLE2 + " where 投稿者ID = ?", 投稿者ID);} public int ファイルgetCountBy投稿者ID( Integer 投稿者ID ) {return this.jdbcTemplate.queryForInt("select count(*) from " + TABLE3 + " where 投稿者ID = ?", 投稿者ID);} // 選択条件あり.id で選択して、投稿者Dso オブジェクトを出力 (投稿者ID が主キーならば 投稿者Dso オブジェクトは1つ) public 投稿者Dso select投稿者By投稿者ID( Integer 投稿者ID ) { return this.jdbcTemplate.queryForObject( "select * from " + TABLE + " where 投稿者ID = ?", new org.springframework.jdbc.core.simple.ParameterizedRowMapper<投稿者Dso>() { public 投稿者Dso mapRow(ResultSet rs, int rowNum) throws SQLException { 投稿者Dso p = new 投稿者Dso(); p.set投稿者ID(rs.getInt("投稿者ID")); p.set名前表記(rs.getString("名前表記")); p.set漢字姓(rs.getString("漢字姓")); p.setかな姓(rs.getString("かな姓")); p.set漢字名(rs.getString("漢字名")); p.setかな名(rs.getString("かな名")); p.set性別(rs.getString("性別")); p.set住所(rs.getString("住所")); p.set年齢(rs.getInt("年齢")); p.set電話番号(rs.getString("電話番号")); return p; } }, 投稿者ID ); } }
package hoge.hoge.com; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class HelloWorld { public static void main(String[] args) { DataSourceFactory dataSourceFactory = new DataSourceFactory(); DriverManagerDataSource dataSource = dataSourceFactory.connect(); 評価データDao e = new 評価データDao(); e.setDataSource(dataSource); // テーブル定義 //dropするテーブルが存在しない場合drop時にエラーが発生し、後続の処理が進まない e.drop投稿者(); e.create投稿者(); e.drop作品評価(); e.create作品評価(); e.dropファイル(); e.createファイル(); // 更新と問い合わせ実行 e.insert投稿者(1,"日本語","山田","やまだ","花太郎","はなたろう","M","福岡県福岡市東区箱崎", 21,"090-2451-5788"); e.insert作品評価(1,"2007-9-025","ディジタル画像処理",null,"CG−ARTS協会",null,"良い","画像処理技術に関してわかりやすく解説されている"); e.insert作品評価(1,"2007-09-25","ディジタル画像処理",null,"CG‐ARTS協会",null,"良い","画像処理技術に関してわかりやすく解説されている"); e.insert作品評価(1,"2006-11-25","システムバイオロジーの展開","北野宏明",null,null,"普通","システムバイオジーについて理解を深めることができた"); e.insert作品評価(1,"2007-09-26","オブジェクト指向データベース",null,null,null,"悪い","オブジェクト指向データベースを用いたシステム開発の特徴について理解することができた"); e.insert投稿者(2,"日本語","山本","やまもと","花子","はなこ","F","福岡県北九州市小倉南区曽根", 25,"090-3519-1090"); e.insert作品評価(2,"2007-09-27","関係データベースシステム","平尾隆行",null,null,"良い",null); e.insert作品評価(2,"2007-09-28","画像処理アルゴリズム","斉藤恒雄","近代科学社","初版","良い","画像処理に関するアルゴリズムについて理解を深めることができた"); e.insertファイル("sample1.xml",1); e.insertファイル("sample2.xml",2); e.set漢字姓(2, "山元"); System.out.println(" getCount投稿者() = " + e.getCount投稿者() ); System.out.println(" getCount作品評価() = " + e.getCount作品評価() ); System.out.println(" getCountファイル() = " + e.getCountファイル() ); System.out.println(" getAll漢字氏名() = " + e.getAll漢字氏名() ); System.out.println(" getAll投稿者ID() = " + e.getAll投稿者ID() ); System.out.println(" getAll投稿者() = " + e.getAll投稿者() ); System.out.println(" getAll作品評価() = " + e.getAll作品評価() ); System.out.println(" getAllファイル() = " + e.getAllファイル() ); System.out.println(" getAll投稿者Dso() = " + e.getAll投稿者Dso() ); System.out.println(" 投稿者getCountBy投稿者ID() = " + e.投稿者getCountBy投稿者ID(1) ); System.out.println(" 作品評価getCountBy投稿者ID() = " + e.作品評価getCountBy投稿者ID(1) ); System.out.println(" ファイルgetCountBy投稿者ID() = " + e.ファイルgetCountBy投稿者ID(1) ); /* */ // 問い合わせ結果を 投稿者Dsoに格納するもの if ( e.投稿者getCountBy投稿者ID(1) > 0 ) { 投稿者Dso p = e.select投稿者By投稿者ID(1); System.out.println(" select投稿者By投稿者ID(1) = " + p + ", 投稿者ID = " + p.get投稿者ID() + ", 漢字姓 = " +p.get漢字姓() + ", 漢字名 = " +p.get漢字名() ); } else { System.out.println(" select投稿者By投稿者ID(1) = 0"); } if ( e.投稿者getCountBy投稿者ID(999) > 0 ) { 投稿者Dso p = e.select投稿者By投稿者ID(999); System.out.println(" select投稿者By投稿者ID(999) = " + p + ", 投稿者ID = " + p.get投稿者ID() + ", 漢字姓 = " +p.get漢字姓() + ", 漢字名 = " +p.get漢字名() ); } else { System.out.println(" select投稿者By投稿者ID(999) = 0"); } } }
実行結果の例
getCount投稿者() = 2 getCount作品評価() = 5 getCountファイル() = 2 getAll漢字氏名() = [{漢字姓=山田, 漢字名=花太郎}, {漢字姓=山元, 漢字名=花子}] getAll投稿者ID() = [{投稿者ID=1}, {投稿者ID=2}] getAll投稿者() = [{投稿者ID=1, 名前表記=日本語, 漢字姓=山田, かな姓=やまだ, 漢字名=花太郎, かな名=はなたろう, 性別=M, 住所=福岡県福岡市東区箱崎, 年齢=21, 電話番号=090-2451-5788}, {投稿者ID=2, 名前表記=日本語, 漢字姓=山元, かな姓=やまもと, 漢字名=花子, かな名=はなこ, 性別=F, 住所=福岡県北九州市小倉南区曽根, 年齢=25, 電話番号=090-3519-1090}] getAll作品評価() = [{投稿者ID=1, 作成日=2007-09-25, タイトル=ディジタル画像処理, 著者名=null, 発行所=CG‐ARTS協会, 版=null, 評価=良い, 感想=画像処理技術に関してわかりやすく解説されている}, {投稿者ID=1, 作成日=2006-11-25, タイトル=システムバイオロジーの展開, 著者名=北野宏明, 発行所=null, 版=null, 評価=普通, 感想=システムバイオジーについて理解を深めることができた}, {投稿者ID=1, 作成日=2007-09-26, タイトル=オブジェクト指向データベース, 著者名=null, 発行所=null, 版=null, 評価=悪い, 感想=オブジェクト指向データベースを用いたシステム開発の特徴について理解することができた}, {投稿者ID=2, 作成日=2007-09-27, タイトル=関係データベースシステム, 著者名=平尾隆行, 発行所=null, 版=null, 評価=良い, 感想=null}, {投稿者ID=2, 作成日=2007-09-28, タイトル=画像処理アルゴリズム, 著者名=斉藤恒雄, 発行所=近代科学社, 版=初版, 評価=良い, 感想=画像処理に関するアルゴリズムについて理解を深めることができた}] getAllファイル() = [{ファイル名=sample1.xml, 投稿者ID=1}, {ファイル名=sample2.xml, 投稿者ID=2}] getAll投稿者Dso() = [hoge.hoge.com.投稿者Dso@100ab23, hoge.hoge.com.投稿者Dso@e3b895] 投稿者getCountBy投稿者ID() = 1 作品評価getCountBy投稿者ID() = 3 ファイルgetCountBy投稿者ID() = 1 select投稿者By投稿者ID(1) = hoge.hoge.com.投稿者Dso@1749757, 投稿者ID = 1, 漢字姓 = 山田, 漢字名 = 花太郎 select投稿者By投稿者ID(999) = 0