前章で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 ArrayList getShohinData() 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 ArrayList execute() {
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
ArrayList shohinList = 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ですので、それと合わせて参考にしてください。