🙌

【初心者向け/ITスクール34日】JDBCを通してMVCパターンを具象する方法

2023/08/28に公開

はじめに

今日は、ITスクールに通った34日目の日で、今日学んだ知識を記事にシェアしたいと思います。本記事が、ITを勉強を始めた方々にもロードマップになればいいと思います。

34日目は、JDBCを通して、Oracle DBMSに繋ぎ、Javaを通してMVCパターンを具象する実習をしました。自由課題として、先生からヒントなしという予告がありましたので、直接実践でまず経験してみました。

一つの機能を作成することは大丈夫でしたが、それは構造化してまとめることがとても難しかったです。例えば、Connectionはどこで配置するか、Scannerはどこに配置するかのように、Classの役割を決めることはとても難しかったと思います。


以前、ダウンロードをした画像になりますが、URLを忘れました


MMODELとして、DBにデーターを送ったり、もらったりする役割で、ビジネスロジックとデーターを扱うアプリケーションです。クライアントには目に見えない領域で、
いわゆるCRUDを担当します。DAOを通して具象しました。

VVIEWとして、コンソール(本来ならhtml)になり、入力と結果の出力を担当します。クライアントにメイル画面だと考えば分かりやすいです。

CControllerとして、直接つながらいMとVの架け橋みたいなものだと捉えたらいいと思います。

1.DB作成

まずはVとMを通してデーターを交換するためには、まずデーターをもらう器が必要になります。
DBをそのようあ役割です。

やはり、DMLよりはDDL、性格にモデリングがとても難しいと痛感しました。

CREATE TABLE TORIKIZOKU(
     t_location VARCHAR2(20 CHAR) PRIMARY KEY,
     t_name VARCHAR2(10 CHAR) NOT NULL,
     t_seat NUMBER(3) NOT NULL
); 

CREATE TABLE RESERVATION(
	r_no NUMBER(3) PRIMARY KEY,
    r_name VARCHAR2(10 CHAR) NOT NULL,
	r_time DATE NOT NULL,
    r_phonenum VARCHAR2(20 CHAR) NOT NULL,
    r_location VARCHAR2(20 CHAR)
);

CREATE SEQUENCE RESERVATION_SEQ;

2.DTO(VO)作成

テーブルはエンティティの集まり、要するにオブジェクトの集まりだとも言えます。
そのため、DTOはテーブルごとに作成します。

//field テーブルの属性名とデータータイプ
//constuructor basic, all fieldsコンストラクタ
//getter setter 

Reservationのデーターをjava.util.Dateをimportします。
後ほど、java.sql.Dateに変換します。

3.DB Manager作成

コードを減らすために、Connectionとcloseのみ担当するクラスを作成します。

package com.hyon.db.manager;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class HyonDBManager {

  public static Connection getConnection() throws SQLException {
	  String address = "jdbc:oracle:thin:@localhost:1521:xe";		  return DriverManager.getConnection(address, "id", "pw");
	}

   public static void close(Connection con, PreparedStatement pstmt, ResultSet rs) {
	   try {
		rs.close();
	   }catch(Exception e){
	   }try {
		pstmt.close();
	   }catch(Exception e) {  
	   }try {
		con.close();
	   }catch(Exception e) {
		}
	}
}

4.ConsoleScreen

Consoleの最初メニュおよび最終結果出力メソッド

ConsoleScreen

public static int showMenu(){
Scanner sc = new Scanner(System.in);
System.out.printf("%-23s%-20s%-20s\n", "1. 予約する", "2. 店舗登録", "3. 全体予約確認");
System.out.printf("%-20s%-20s%-20s\n", "4. 全体店舗検索", "5. 店舗検索", "6. 予約検索");
System.out.printf("%-20s%-20s%-20s\n", "7. 予約情報訂正", "8. 予約キャンセル", "9. 終了");
System.out.println();
System.out.print("メニュー番号 : ");
   return sc.nextInt();
}
	  
public static void printResult(String result) {
	System.out.println(result);
   }

main

Controller

public class Controller {
    	
  public static void main(String[] args) {
       int menu;
       System.out.println("Torikizoku Program Start!");
       while(true) {
	   try {
		menu =ConsoleScreen.showMenu();
		if(menu==9) {
			System.out.println("bye bye");
			System.exit(0);
			}
	else if(menu==1) {ConsoleScreen.printResult(null);}
	else if(menu==2) {ConsoleScreen.printResult(null);}
	else if(menu==3) {ConsoleScreen.printResult(null);}
	else if(menu==4) {ConsoleScreen.printResult(null);}
	else if(menu==5) {ConsoleScreen.printResult(null);}
	else if(menu==6) {ConsoleScreen.printResult(null);}
	else if(menu==7) {ConsoleScreen.printResult(null);}
	else if(menu==8) {ConsoleScreen.printResult(null);}
	} catch (Exception e) {
		e.printStackTrace();
		}
	}
   }//main
}//class

ViewとControllerの役割をどこからどこまでするかを決められなかったので、進むことができませんでした。
メニュをコンソールに出力し、menunumまで入力するメソッドです。

Controllerをmainにし、menunumからもらった数字によって、違うDAOのメソッドを呼び出す仕組みに設定しました。9番を押せば、終了になるプログラムです。
結局、この仕組みを組めるかどうかによって、進みが変わったと思います。

メニューごとに案内文を出力し、データーを入力するメソッド

基本的な仕組みが出来上がったので、残りはメニューごとにUserが入力してもらうためのメソッドを作成し、それをDTOを媒体に伝えることです。
ですから、このタイミングで入力した値をパラメーターにし、DTOのオブジェクトを生成します。Controllerはあくまでその値をDAOに繋がる役割だけです。

5. CUD

まず、CUDの場合はこの入力してもらったデーターをDTOに込めて、伝える必要がありますので。DTOのオブジェクトを生成します。

ConsoleScreen

//1. 予約情報入力

 public static Reservation ShowReserveEnrollMenu() throws ParseException {
   Scanner sc = new Scanner(System.in);
		    
    System.out.print("予約者名 :  ");
	String name = sc.next();	  
	System.out.print("予約時間(YYYY-MM-DD/HH:mm) : ");
	String when = sc.next();	  
	SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD/HH:mm");
	Date when2 = sdf.parse(when);
	System.out.print("携帯番号 :  ");
	String phoneNum = sc.next();	  
	System.out.print("支店名 :  ");
	String location = sc.next();	 
		    
	return new Reservation(0, name, when2, phoneNum, location);
		    
  }


//2. 店を登録するメソッド-> TorikizokuのDTO
public static Torikizoku showTorikiEnrollMenu(){
    Scanner sc = new Scanner(System.in);
    
    System.out.print("支店名 :  ");
    String location = sc.next();	  
    System.out.print("店長名 :  ");
    String name = sc.next();	  
    System.out.print("座席数 :  ");
    int seat = sc.nextInt();
		  
    return new Torikizoku(location, name, seat);	  
     
}
Controller
   
public static void main(String[] args) {
	
int menu;
String result;
Torikizoku t = null;
Reservation r = null;
		
System.out.println("Torikizoku Program Start!");
while(true) {
    try {
	menu =ConsoleScreen.showMenu();
	  if(menu==9) {
		System.out.println("bye bye");
		System.exit(0);
	}
	else if(menu==1) {
		r = ConsoleScreen.ShowReserveEnrollMenu();
	    result = DAO.insertReservation(r);
		ConsoleScreen.printResult(result);
		 }
	else if(menu==2) {
		t = ConsoleScreen.showTorikiEnrollMenu();
		//result = DAO.method(t)
		//ConsoleScreen.printResult(result);
		}

Dao

//1
public static String insertReservation(Reservation r) {		
	Connection con = null;
	PreparedStatement ptsmt = null;
	
	try {
	  con = HyonDBManager.getConnection();
			
	 String sql="INSERT INTO RESERVATION VALUES"
	 + "(RESERVATION_SEQ.NEXTVAL,?,?,?,?)";
			
	ptsmt = con.prepareStatement(sql);
	ptsmt.setString(1, r.getName());
	ptsmt.setDate(2, new Date(r.getWhen().getTime()));
	ptsmt.setString(3, r.getPhoneNum());
	ptsmt.setString(4, r.getLocation());
					
	if(ptsmt.executeUpdate()==1) {
			return "予約成功";
		}
	   return "";  // java文法上、必修
	}catch(Exception e) {
	 	e.printStackTrace();
		return "予約失敗";
	}finally {
		HyonDBManager.close(con, ptsmt, null);
	   }	
	}
	
//2
public static String insertTorikizoku(Torikizoku t) {		
	Connection con = null;
	PreparedStatement ptsmt = null;
	
	try {
	   con = HyonDBManager.getConnection();
			
	  String sql="INSERT INTO TORIKIZOKU VALUES"
	+ "(?,?,?)";
			
	ptsmt = con.prepareStatement(sql);
	ptsmt.setString(1, t.getLocation());
	ptsmt.setString(2, t.getName());
	ptsmt.setInt(3, t.getSeat());
					
	if(ptsmt.executeUpdate()==1) {
		return "店舗登録成功";
	 	}
	 return "";  // java文法上、必修
	 }catch(Exception e) {
		return "予約失敗";
	}finally {
		HyonDBManager.close(con, ptsmt, null);
	}
		
    }

のこりは、DAOからデーターを処理し、Stringにリターンすることだけです。
事前に、作ったConsoleScreenから出力したら終わりです。

6. R

データーを読みたい場合は、逆にDAOからDBのデーターをアウトプットし、
Viewからそのデーターを出力します。

DAO

ResultSetからクエリの結果を込め、Iterator、DTOを活用して
ArrayListに込めます。

Dao
//3
public static ArrayList<Reservation> selectAllReserve(){
  Connection con = null;
  PreparedStatement ptsmt = null;
  ResultSet rs = null;
      
   try {
       con = HyonDBManager.getConnection();
       String sql = "SELECT * FROM RESERVATION";
       ptsmt = con.prepareStatement(sql);
       rs = ptsmt.executeQuery();
    	  
       ArrayList<Reservation> rlist = new ArrayList<>();
       while(rs.next()) {
    	  Reservation r = new Reservation();
    	  r.setNo(rs.getInt("r_no"));
	  r.setName(rs.getString("r_name"));
	  r.setWhen(rs.getDate("r_time"));
	  r.setPhoneNum(rs.getString("r_phonenum"));
	  r.setLocation(rs.getString("r_location"));
	  rlist.add(r);
    	  }
    	 return rlist; 
      }catch(Exception e) {
    	  return null;
      }finally {
    	  HyonDBManager.close(con, ptsmt, rs);
      }
	
	
   }
	
//4
public static ArrayList<Torikizoku> selectAllToriki(){
   Connection con = null;
   PreparedStatement ptsmt = null;
   ResultSet rs = null;
			
      try {
	con = HyonDBManager.getConnection();
	String sql = "SELECT * FROM TORIKIZOKU";
	ptsmt = con.prepareStatement(sql);
	rs = ptsmt.executeQuery();
			
	ArrayList<Torikizoku>tlist = new ArrayList<>();
	while(rs.next()) {
		Torikizoku t = new Torikizoku();
		t.setLocation(rs.getString("t_location")); 
		t.setName(rs.getString("t_name")); 
		t.setSeat(rs.getInt("t_seat")); 
		tlist.add(t);
	     }
	  return tlist;
      	} catch (Exception e) {
		return null;
	}finally {
		HyonDBManager.close(con, ptsmt, rs);
	}
    }

ConsoleScreen

ConsoleScreen
  //3
public static void showReserveListResultMenu(ArrayList<Reservation> rlist) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd E a hh:mm");
      for (Reservation r : rlist) {
	 System.out.printf("예약번호:%-3d" , r.getNo());
	 System.out.printf("예약자명:%-6s " , r.getName());
	 System.out.printf("예약시간: %-22s" , sdf.format(r.getWhen()));
	 System.out.printf("핸드폰 번호: %-15s" , r.getPhoneNum());
	 System.out.printf("지점명: %-6s\n", r.getLocation());
	}
     }
	  
  //4
 public static void showTorikiListResultMenu(ArrayList<Torikizoku> tlist) {
    for (Torikizoku t : tlist) {
	 System.out.printf("지점명:%-15s" , t.getLocation());
	 System.out.printf("지점잠명:%-15s " , t.getName());
	 System.out.printf("좌석수: %-3d\n" , t.getSeat());
	}
  }
  

Discussion