前章でSelectを実行して表示してみましたので、少し加えてCRUDしてみましょう。
MVCをご存じでしょうか。以前やっていますので、Servletでデータベースを読んでください。
MVCのためのModelを作る
Model,View,Cotrolを組み合わせて作っていきます
JavaBeansでMVCしていく
今回扱うテーブルは、前回の章で扱ったshohinテーブルです。主キーがshohin_idでshohin_mei,shohin_bunrui,hanbai_tanka,shiire_tanka,torokubiの項目があります。
これをやり取りするクラスを作りましょう。
作る場所としてフォルダーを作っていきます。
| Main.java | Main.class | +---dao | \---model ShohinData.java
Mainの階層の下にmodelフォルダーを作り、そこにShohinData.javaでクラスを作ります。daoはこれから作っていきます。
package model; import java.io.Serializable; import java.util.Date; public class ShohinData implements Serializable{ private String si; //shohin_id private String sm; //shohin_mei private String sb; //shohin_bunrui private int ht; //hanbai_tanka private int st; //shiire_tanka private Date tb; //torokubi public ShohinData() {} public ShohinData(String si, String sm, String sb, int ht, int st, Date tb) { this.si = si; this.sm = sm; this.sb = sb; this.ht = ht; this.st = st; this.tb = tb; } public String getSi() { return si; } public void setSi(String si) { this.si = si; } public String getSm() { return sm; } public void setSm(String sm) { this.sm = sm; } public String getSb() { return sb; } public void setSb(String sb) { this.sb = sb; } public int getHt() { return ht; } public void setHt(int ht) { this.ht = ht; } public int getSt() { return st; } public void setSt(int st) { this.st = st; } public Date getTb() { return tb; } public void setTb(Date tb) { this.tb = tb; } }
フィールドとコンストラクタとセッターゲッターです。非常に単純です。
実は、VsCodeでセッターゲッターは簡単に作れます。フィールドを宣言したら、その下で右クリック ソースアクション->Generate getter and setter を選択するだけです。
DAOを作る
前回作ったMain.javaは、その中でデータベースへの接続、SQLの発行、内容表示、クローズをやっています。これをメインでやってしまうと、それぞれのRead,Updateがメインの中で煩雑に混じってしまうので、それをそれぞれのソースに分けて、それぞれでオープン、操作、クローズをするようにするのがDAOです。
まずはSelect文を発行している前章の内容をListDAO.javaというソースにまとめてdaoフォルダーに作成します。
今後作っていくファイルについてもまとめて紹介しておきます。
| Main.java | +---dao | DeleteDAO.java | InsertDAO.java | ListDAO.java | UpdateDAO.java | \---model DeleteLogic.java InsertLogic.java ListLogic.java ShohinData.java UpdateLogic.java
ListDAO.javaをMain配下daoフォルダーに作ります。
package dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Date; import java.util.ArrayList; import model.ShohinData; public class ListDAO { public static ArrayListgetShohinData() throws ClassNotFoundException{ Connection con = null; ArrayList am = new ArrayList<>(); try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch(ClassNotFoundException e) { throw new IllegalStateException("ドライバーのロードに失敗しました"); } try { con = DriverManager.getConnection("jdbc:sqlserver://localhost\\SQLEXPRESS;databaseName=shop;IntegratedSecurity=true;TrustServerCertificate=true;"); //step2 送信すべきSQL文のひな形を準備 PreparedStatement pstmt = con.prepareStatement // ("SELECT * FROM Shohin"); ( "Select shohin_id,shohin_mei,shohin_bunrui,hanbai_tanka,coalesce(shiire_tanka,0) as shiire,coalesce(torokubi,'1970-01-01') as toroku from shohin"); //DBMSに検索系を送信 ResultSet r = pstmt.executeQuery(); //処理結果を見る while(r.next()) { String si = r.getString("shohin_id"); String sm = r.getString("shohin_mei"); String sb = r.getString("shohin_bunrui"); int ht = r.getInt("hanbai_tanka"); int st = r.getInt("shiire"); java.sql.Timestamp ts = r.getTimestamp("toroku"); long l = ts.getTime(); java.util.Date d = new Date(l); ShohinData sd = new ShohinData(si,sm,sb,ht,st,d); am.add(sd); } r.close(); pstmt.close(); return am; } catch (SQLException e) { e.printStackTrace(); return null; } finally { if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
select文が以前と変わっています。今回使ったテーブルのデータがところどころ実験のためにNULLで抜けているので、普通に読み込むとエラーで止まってしまいます。そこでcoalesceを使って変換しています。
executeQueryで読み込んだレコードセットを.netx()で回して先ほど作成したShohinDataクラスに詰め込んでArrayListを作り、呼びもとに返しています。
同様に、Insert,Update,Deleteに関してもDAOを作成しておきましょう。
package dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Date; import model.ShohinData; public class InsertDAO { public static boolean insertData(ShohinData sd ) throws ClassNotFoundException{ Connection con = null; try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch(ClassNotFoundException e) { throw new IllegalStateException("ドライバーのロードに失敗しました"); } try { con = DriverManager.getConnection("jdbc:sqlserver://localhost\\SQLEXPRESS;databaseName=shop;IntegratedSecurity=true;TrustServerCertificate=true;"); //step2 送信すべきSQL文のひな形を準備 PreparedStatement pstmt = con.prepareStatement( "insert into shohin (shohin_id,shohin_mei,shohin_bunrui,hanbai_tanka,shiire_tanka,torokubi) VALUES (?,?,?,?,?,?)"); pstmt.setString(1, sd.getSi()); pstmt.setString(2, sd.getSm()); pstmt.setString(3,sd.getSb()); pstmt.setInt(4, sd.getHt()); pstmt.setInt(5, sd.getSt()); Date d = new Date(); long l = d.getTime(); java.sql.Timestamp ts = new java.sql.Timestamp(l); pstmt.setTimestamp(6, ts); int r = pstmt.executeUpdate(); //処理結果を見る pstmt.close(); if (r==1) { return true; } else { return false; } } catch (SQLException e) { e.printStackTrace(); return false; } finally { if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
このように一度DAOを作っておけば、その応用でほかのDAOを作ることができます。
つづいてUpdateをやってみましょう
package dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Date; import model.ShohinData; public class UpdateDAO { public static boolean updateData(ShohinData sd ) throws ClassNotFoundException{ Connection con = null; try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch(ClassNotFoundException e) { throw new IllegalStateException("ドライバーのロードに失敗しました"); } try { con = DriverManager.getConnection("jdbc:sqlserver://localhost\\SQLEXPRESS;databaseName=shop;IntegratedSecurity=true;TrustServerCertificate=true;"); //step2 送信すべきSQL文のひな形を準備 PreparedStatement pstmt = con.prepareStatement( "update shohin set shohin_mei=?,shohin_bunrui=?,hanbai_tanka=?,shiire_tanka=?,torokubi=? WHERE shohin_id=?"); pstmt.setString(6, sd.getSi()); pstmt.setString(1, sd.getSm()); pstmt.setString(2,sd.getSb()); pstmt.setInt(3, sd.getHt()); pstmt.setInt(4, sd.getSt()); Date d = new Date(); long l = d.getTime(); java.sql.Timestamp ts = new java.sql.Timestamp(l); pstmt.setTimestamp(5, ts); int r = pstmt.executeUpdate(); //処理結果を見る pstmt.close(); if (r==1) { return true; } else { return false; } } catch (SQLException e) { e.printStackTrace(); return false; } finally { if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
次は、delete行います。今回は1でtrueとしてますが、1以上にしても大丈夫です。
package dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class DeleteDAO { public static boolean deleteData(String si ) throws ClassNotFoundException{ Connection con = null; try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch(ClassNotFoundException e) { throw new IllegalStateException("ドライバーのロードに失敗しました"); } try { con = DriverManager.getConnection("jdbc:sqlserver://localhost\\SQLEXPRESS;databaseName=shop;IntegratedSecurity=true;TrustServerCertificate=true;"); //step2 送信すべきSQL文のひな形を準備 PreparedStatement pstmt = con.prepareStatement ("DELETE FROM shohin WHERE shohin_id=?"); //ひな形に値を流し込む pstmt.setString(1,si); //DBMSに検索系を送信 int r = pstmt.executeUpdate(); //処理結果を見る pstmt.close(); if (r==1) { return true; } else { return false; } } catch (SQLException e) { e.printStackTrace(); return false; } finally { if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
これらを組み立てる
daoができたので、これらをつないでいきましょう
modelにLogic.javaを追加する
以前のMainからListDAOを作りましたが、するとMainにはデータベースに関することを書かなくて済むようにできるはずです。
今回はmodelにLogic.javaを作成して、そこからDAOを呼び出すようにします。そしてMainからこのLogic.javaを呼び出します。
package model; import java.util.ArrayList; import dao.ListDAO; public class ListLogic { public ArrayListexecute() { ArrayList sd = new ArrayList<>(); try { sd = ListDAO.getShohinData(); } catch (Exception e) { System.out.println(e.getMessage()); } return sd; } }
package model; import dao.InsertDAO; public class InsertLogic { public boolean execute(ShohinData sd) { boolean st = true; try { st = InsertDAO.insertData(sd); } catch (Exception e) { System.out.println(e.getMessage()); st = false; } return st; } }
package model; import dao.UpdateDAO; public class UpdateLogic { public boolean execute(ShohinData sd) { boolean st = true; try { st = UpdateDAO.updateData(sd); } catch (Exception e) { System.out.println(e.getMessage()); st = false; } return st; } }
package model; import dao.DeleteDAO; public class DeleteLogic { public boolean execute(String si) { boolean st = true; try { st = DeleteDAO.deleteData(si); } catch (Exception e) { System.out.println(e.getMessage()); st = false; } return st; } }
これで4つのLogic.javaができましたので、これをMainから呼び出します。
今回は単純のためにフォーム画面は作りません。コマンドプロンプトで実行します。
Select,Insert,Update,Deleteを選択してもらい、必要がデータの入力して、結果を表示してまたループに戻るようにします。
// CLASSPATH に.;c:\Program Files\Java\jdk-21\lib\mssql-jdbc-12.6.1.jre11.jarを入れる //jarファイルをlibに authのdllをsystem32に入れる //javac Main.java // ただしdao,model配下はjavacが届かない時があるので javac dao\ListDAO.java等でコンパイル //java Main import java.text.SimpleDateFormat; import java.util.Scanner; import model.DeleteLogic; import model.InsertLogic; import model.ListLogic; import model.UpdateLogic; import model.ShohinData; import java.util.ArrayList; import java.util.Date; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in,"Shift-JIS"); try { String cmd = ""; String si = ""; //shohin id String sm = ""; //shohin mei String sb = ""; //shohin_bunrui int ht = 0; //hanbai tanka int st = 0; //shiire tanka //bunrui = '事務用品'固定 登録日:今日 boolean loopf = true; while(loopf) { System.out.print("Enter command: E(end) I(insert) U(update) D(delete) S(select) :"); switch(cmd = scanner.nextLine()) { case "E"-> { //end loopf = false; } case "I"-> { //insert System.out.print("shohin_id(00nn): "); si = scanner.nextLine(); System.out.print("shohin_mei: "); sm = scanner.nextLine(); System.out.println("bunri:キッチン用品,事務用品,衣服"); System.out.print("shohin_bunrui: "); sb = scanner.nextLine(); System.out.print("hanbai_tanka: "); ht = scanner.nextInt(); System.out.print("shiire_tanka: "); st = scanner.nextInt(); Date now = new Date(); //今日の日付 long l = now.getTime(); java.sql.Timestamp ts = new java.sql.Timestamp(l); ShohinData sd = new ShohinData(si,sm,sb,ht,st,ts); //Insert処理 InsertLogic insertLogic = new InsertLogic(); boolean ir = insertLogic.execute(sd); if (ir==true) { System.out.println("Insert Scucess"); } else { System.out.println("Error Occured"); } } case "U"-> { //update System.out.print("指定するshohin_id(00nn): "); si = scanner.nextLine(); System.out.print("shohin_mei: "); sm = scanner.nextLine(); System.out.println("bunri:キッチン用品,事務用品,衣服"); System.out.print("shohin_bunrui: "); sb = scanner.nextLine(); System.out.print("hanbai_tanka: "); ht = scanner.nextInt(); System.out.print("shiire_tanka: "); st = scanner.nextInt(); Date now = new Date(); //今日の日付 long l = now.getTime(); java.sql.Timestamp ts = new java.sql.Timestamp(l); ShohinData sd = new ShohinData(si,sm,sb,ht,st,ts); //Update処理 UpdateLogic updateLogic = new UpdateLogic(); boolean ur = updateLogic.execute(sd); if (ur==true) { System.out.println("Insert Scucess"); } else { System.out.println("Error Occured"); } } case "D"-> { //delete System.out.print("shohin_id(00nn): "); si = scanner.nextLine(); //Delete処理 DeleteLogic deleteLogic = new DeleteLogic(); boolean dr = deleteLogic.execute(si); if (dr==true) { System.out.println("Delete Scucess"); } else { System.out.println("Error Occured"); } } case "S"-> { //select ArrayListshohinList = new ArrayList<>(); ListLogic logic = new ListLogic(); shohinList = logic.execute(); final String SFORMAT = "id:%-4s\t name:%-14s\t bunrui:%-8s\t ht:%-8d\t st:%-8d\t Date:%-10s"; SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd"); for( ShohinData sd : shohinList) { String stb = f.format(sd.getTb()); String s = String.format(SFORMAT, sd.getSi(),sd.getSm(),sd.getSb(),sd.getHt(), sd.getSt(),stb); System.out.println(s); } } } } } catch (Exception e) { e.printStackTrace(); } finally { scanner.close(); } } }
コメントにもあるように javac Main.javaでコンパイルしますが、パッケージのコンパイルが完全ではないようなので、それぞれコンパイルした方がよいと思います。mavenでやれば管理できると思いますが、今回はやっていません。
>java Main Enter command: E(end) I(insert) U(update) D(delete) S(select) :S id:0001 name:Tシャツ bunrui:衣服 ht:1000 st:500 Date:2009/09/20 id:0002 name:穴あけパンチ bunrui:事務用品 ht:500 st:320 Date:2009/09/11 id:0003 name:カッターシャツ bunrui:衣服 ht:4000 st:2800 Date:1970/01/01 id:0004 name:包丁 bunrui:キッチン用品 ht:3000 st:2800 Date:2009/09/20 id:0005 name:圧力鍋 bunrui:キッチン用品 ht:6800 st:5000 Date:2009/01/15 id:0006 name:フォーク bunrui:キッチン用品 ht:500 st:0 Date:2009/09/20 id:0007 name:おろしがね bunrui:キッチン用品 ht:880 st:790 Date:2008/04/28 id:0008 name:ボールペン bunrui:事務用品 ht:100 st:0 Date:2009/11/11 Enter command: E(end) I(insert) U(update) D(delete) S(select) :I shohin_id(00nn): 0009 shohin_mei: 印鑑 bunri:キッチン用品,事務用品,衣服 shohin_bunrui: 事務用品 hanbai_tanka: 95 shiire_tanka: 10 Insert Scucess Enter command: E(end) I(insert) U(update) D(delete) S(select) :Enter command: E(end) I(insert) U(update) D(delete) S(select) :U 指定するshohin_id(00nn): 0009 shohin_mei: 印鑑 bunri:キッチン用品,事務用品,衣服 shohin_bunrui: 事務用品 hanbai_tanka: 130 shiire_tanka: 30 Insert Scucess Enter command: E(end) I(insert) U(update) D(delete) S(select) :Enter command: E(end) I(insert) U(update) D(delete) S(select) :S id:0001 name:Tシャツ bunrui:衣服 ht:1000 st:500 Date:2009/09/20 id:0002 name:穴あけパンチ bunrui:事務用品 ht:500 st:320 Date:2009/09/11 id:0003 name:カッターシャツ bunrui:衣服 ht:4000 st:2800 Date:1970/01/01 id:0004 name:包丁 bunrui:キッチン用品 ht:3000 st:2800 Date:2009/09/20 id:0005 name:圧力鍋 bunrui:キッチン用品 ht:6800 st:5000 Date:2009/01/15 id:0006 name:フォーク bunrui:キッチン用品 ht:500 st:0 Date:2009/09/20 id:0007 name:おろしがね bunrui:キッチン用品 ht:880 st:790 Date:2008/04/28 id:0008 name:ボールペン bunrui:事務用品 ht:100 st:0 Date:2009/11/11 id:0009 name:印鑑 bunrui:事務用品 ht:130 st:30 Date:2024/04/08 Enter command: E(end) I(insert) U(update) D(delete) S(select) :D shohin_id(00nn): 0009 Delete Scucess Enter command: E(end) I(insert) U(update) D(delete) S(select) :S id:0001 name:Tシャツ bunrui:衣服 ht:1000 st:500 Date:2009/09/20 id:0002 name:穴あけパンチ bunrui:事務用品 ht:500 st:320 Date:2009/09/11 id:0003 name:カッターシャツ bunrui:衣服 ht:4000 st:2800 Date:1970/01/01 id:0004 name:包丁 bunrui:キッチン用品 ht:3000 st:2800 Date:2009/09/20 id:0005 name:圧力鍋 bunrui:キッチン用品 ht:6800 st:5000 Date:2009/01/15 id:0006 name:フォーク bunrui:キッチン用品 ht:500 st:0 Date:2009/09/20 id:0007 name:おろしがね bunrui:キッチン用品 ht:880 st:790 Date:2008/04/28 id:0008 name:ボールペン bunrui:事務用品 ht:100 st:0 Date:2009/11/11 Enter command: E(end) I(insert) U(update) D(delete) S(select) :E
コマンドプロンプトからの入力にしていますので、Scannerから Shift-JISで入力しています。これをしないと文字化けします。
さて、これでCRUDができました。教科書のサンプルはPostgreSQLですので、それと合わせて参考にしてください。