Learn & Record

JAVA, MariaDB (JDBC UPDATE, DELETE, 디자인패턴, 싱글턴 패턴, 어댑터 패턴, 빌더패턴, MVC패턴, MVC패턴+DB연결) 본문

Dev/SQL

JAVA, MariaDB (JDBC UPDATE, DELETE, 디자인패턴, 싱글턴 패턴, 어댑터 패턴, 빌더패턴, MVC패턴, MVC패턴+DB연결)

Walker_ 2024. 2. 16. 13:47

1. JDBC UPDATE 구현

 [ DBUpdate 파일 ] 

package ch_01.day2402141516;

import java.sql.SQLException;
import java.util.Scanner;

public class DBUpdate extends DBSelect{
    protected User modifyUser(){
        User user = new User();
        Scanner scanner = new Scanner(System.in);

        Boolean validate = false;
        String validateTemp;
        do {
            System.out.println("정보 수정 할 회원의 아이디를 입력하세요: ");
            user.userID = scanner.nextLine();
            System.out.println("회원의 이름을 입력하세요 : ");
            user.name = scanner.nextLine();
            System.out.println("회원의 나이를 입력하세요 : ");
            user.age = Integer.parseInt(scanner.nextLine());
            System.out.println("회원의 직업을 입력하세요 : ");
            user.job = scanner.nextLine();

            System.out.println("수정 된 회원 : " + user.userID + " / " + user.name + " / "
            + user.age + " / " + user.job +"이 맞습니까? (y/n)");
            validateTemp = scanner.nextLine();
            validate = !validateTemp.equals("y");
        }while (validate);
        scanner.close();
        return user;
    }
    
    public void updateUser() throws SQLException {
        User user = modifyUser();
        String updateSQL = "UPDATE uUser SET name = ?, age = ?, job = ? WHERE userID = ? ";
        
        preparedStatement = conn.prepareStatement(updateSQL); // 쿼리 실행 준비
        // ? 자리에 순서대로 데이터 입력
        preparedStatement.setString(1, user.name);
        preparedStatement.setInt(2, user.age);
        preparedStatement.setString(3, user.job);
        preparedStatement.setString(4, user.userID);
        int cnt = preparedStatement.executeUpdate(); // 영향을 받은 데이터 갯수 반환
        // pstmt.excuteQuery() : select
        // pstmt.excuteUpdate() : insert, update, delete ..
        if(cnt ==1 ){
            System.out.println("영향 받은 데이터 : :"+cnt);
            System.out.println("데이터 수정에 성공했습니다.");
        } else {
            System.out.println("데이터 수정에 실패했습니다.");
        }
    }
}

 

 - 기능 구현 코드 [ My_06_UpdateUser] 파일

package ch_01.day240214_16;
import java.sql.SQLException;

public class My_06_UpdateUser {
    public static void main(String[] args) throws SQLException {
        DBUpdate myDB = new DBUpdate();
        myDB.connectDB(); // DB 클래스에 선언된 메서드
        myDB.getAllUser(); // DBSelect 클래스에 선언된 메서드
        myDB.updateUser();
        myDB.getAllUser(); // DBSelect 클래스에 선언된 메서드
        myDB.closeDB(); // DB 클래스에 선언된 메서드
    }
}

 

2. JDBC DELETE 구현

package ch_01.day240214_16;

import java.sql.SQLException;
import java.util.Scanner;

public class DBDelete extends DBSelect{
    public void deleteUser() throws SQLException{
        Scanner scanner = new Scanner(System.in);

        System.out.println("삭제 할 유저의 아이디를 입력하세요 : ");
        String userID = scanner.nextLine();

        String deleteSQL = "DELETE FROM tUser WHERE userID='" + userID + "' ";

        preparedStatement = conn.prepareStatement(deleteSQL); // 쿼리 실행 준비
        int cnt = preparedStatement.executeUpdate(); // 영향을 받은 데이터 갯수 반환
        // pstmt.excuteQuerey() : select
        // pstmt.escuteUpdate() : insert, update, delete .. 
        
        if (cnt == 1) {
            System.out.println("영향 받은 데이터 : : " + cnt);
            System.out.println("데이터 삭제에 성공했습니다.");
        } else {
            System.out.println("데이터 삭제에 실패했습니다.");
        }
        scanner.close();
    }
}

 

package ch_01.day240214_16;

import java.sql.SQLException;

public class My_08_DeleteUser {
    public static void main(String[] args) throws SQLException {
        DBDelete myDB = new DBDelete();
        myDB.connectDB(); // 데이터베이스 연결
        myDB.getAllUser(); // 모든 유저 보여줌
        myDB.deleteUser(); // 삭제 처리
        myDB.getAllUser(); // 모든 유저 보여줌 > 삭제 확인 용도
        myDB.closeDB(); // 데이터베이스 연결 닫기
        
    }
}

 

3. 디자인 패턴 Design Pattern

 - 지금까지 수많은 소프트웨어 개발자들이 오랜 세월에 걸쳐 쌓아 온 프로그램 설계 노하루를 집대성한 것

 - 디자인 패턴의 개념은 1995년 Gof(Gang of Four)라고 불리는 저자 네 명 (에릭 감마, 리처드 헬름, 랄프 존슨, 존 블라)이

 - 쓴 "Gof의 디자인 패턴"에서 처음 소개된 이후 많은 프로그래머들의 연구 대상이 되었음

 

 - 객체 지향 프로그램을 어떻게 구현해야 더 유연하고 재활용성이 높은 프로그램을 만들 수 있는지를 정리한 내용

 - 구조화 되지 않은 프로그램은 프로그램의 구성 요소가 강하게 결합하기 때문에 프로그램의 유지보수와 확장이 어려움

 - 간단히 말해서 프로그램 특성에 따른 설계 유형을 이론화한 내용.

 - 따라서 디자인 패턴은 자바는 물론 C++이나 C# 같은 객체 지향 언어에도 작용하여 구현할 수 있음

 

4. 싱글턴 패턴 Singleton pattern

 - 객체 지향 프로그램에서 인스턴스를 단 하나만 생성하는 디자인 패턴

 

5. 어댑터 패턴 Adapter Pattern

 - 어댑터를 번역하면 변환기 converter라고 할 수 있음

 - 변환기의 역할을 서로 다른 두 인터페이스 사이에 통신이 가능하게 하는 것

 - ODBC, JDBC가 어댑터 패턴을 이용해 다양한 데이터베이스 시스템을 단일한 인터페이스로 조작가능

 - * 자바의 경우 DB 종류에 구분없이, JDBC로 동일하게 사용가능

 

[ AdpaterNo.java ]

package ch_01.day240214_16.adapter;

class WorkMan {void runWork() {System.out.println("work");}
}

class StudyStudent {void runStudy() {System.out.println("study");}
}
public class AdapterNo {
    public static void main(String[] args) {
        WorkMan workMan = new WorkMan();
        StudyStudent studyStudent = new StudyStudent();

        // 유사한 기능이라하더라도 새로운 클래스가 생성이 되면 메서드의 사용법을 공부해야 함
        workMan.runWork();
        studyStudent.runStudy();
    }
}

 

[ Adapter.java ]

package ch_01.day240214_16.adapter;

import javax.swing.text.Style;

interface AdapterService {
    void runService();
}

class AdapterServiceA implements AdapterService {
    WorkMan workMan = new WorkMan();

    @Override
    public void runService() { workMan.runWork();}
}

class AdapterServiceB implements AdapterService{
    StudyStudent studyStudent = new StudyStudent();

    @Override
    public void runService() { studyStudent.runStudy();}
}
public class Adapter {
    public static void main(String[] args) {
        AdapterService asa1 = new AdapterServiceA();
        AdapterService asb1 = new AdapterServiceB();

        asa1.runService();
        asb1.runService();
    }
}

 

6. 빌더패턴 

 - 객체 생성을 하는데, 해당 클래스의 멤버 변수는 8개

 - name, age, address, grade, tel, email, reserve, hobby

 - 이름 항상 있지만, 나머지는 변동됨. 생성자를 몇 개 만들어야 할까

package ch_01.day240214_16.patternb;

public class Account {
    private int accID;
    private int balance;
    private String cusName;

    // 모든 필드를 사용하는 생성자가 필요
    public Account(int accID, int balance, String cusName) {
        this.accID = accID;
        this.balance = balance;
        this.cusName = cusName;
    }

    @Override
    public String toString() {
        return "Acount{" +
                "accID=" + accID +
                ", balance=" + balance +
                ", cusName='" + cusName + '\'' +
                '}';
    }

    public static class Builder {
        // 외부 클래스와 동일한 필드를 가짐
        private int accID;
        private int balance;
        private String cusName;

        Builder() {

        }

        public Builder accID(int accID) {
            this.accID = accID;
            return this;
        }

        public Builder balance(int balance) {
            this.balance = balance;
            return this;
        }

        public Builder cusName(String cusName) {
            this.cusName = cusName;
            return this;
        }

        public Account Builder() {
            return new Account(this.accID, this.balance, this.cusName);
        }

    }
}

 

- 빌더 패턴으로 유연하게 생성자를 활용 가능

package ch_01.day240214_16.patternb;


public class Test {
    public static void main(String[] args) {
        // 계좌번호를 초기값으로 객체 생성
        Account account1 = new Account.Builder().accID(222).Builder();
        System.out.println(account1);

        // 계좌번호, 잔액을 초기값으로 객체 생성
        Account account2 = new Account.Builder().accID(222).balance(10000).Builder();
        System.out.println(account2);

        // 계좌번호, 잔액, 예금주를 초기값으로 객체 생성
        Account account3 = new Account.Builder().accID(222).balance(10000).cusName("홍길동").Builder();
        System.out.println(account3);

        // 잔액, 예금주를 초기값으로 객체 생성
        Account account4 = new Account.Builder().balance(10000).cusName("홍길동").Builder();
        System.out.println(account4);
        
        // 예금주를 초기값으로 객체 생성
        Account account5 = new Account.Builder().cusName("홍길동").Builder();
        System.out.println(account5);
    }
}

 

7. MVC 패턴 Model View Controller

 - 디자인 패턴의 일종으로 전체 프로그램의 구조와 관련된 디자인 패턴

 - 애플리케이션 내부 데이터와 사용자에게 표시하는 정보와 분리

 - 사용성과 확장성이 용이하다는 장점이 있고, 복잡해질수록 모델과 뷰의 관계가 복잡해지는 단점

 

 - 모델 : 데이터인 데이터베이스, 상수, 변수를 뜻함.데이터 혹은 데이터를 처리하는 영역을 의미

 - 뷰 : 모델을 기반으로 사용자가 볼 수 있는 화면을 뜻함. 사용자 인터페이스 요소

 - 컨트롤러 : 요청을 처리하는 존재로 뷰와 모델 사이의 중간 통신 역할. 모델에서 필요한 데이터를 처리하고, 결과 뷰 전송

 

[DTO (Data Trinsfer Object)]

package ch_01.day240216.mvc;

/* DTO(Data Transfer Object), VO(Value Object)
로직을 갖고 있지 않는 순수한 데이터 객체이며 속성과 그 속성에 접근하기 위한 getter, setter 메소드만 가진 클래스
 */
public class Account {
    private int id; // 계좌
    private String name; // 이름
    private long balance; // 잔액

    public Account(){
        
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getBalance() {
        return balance;
    }

    public void setBalance(long balance) {
        this.balance = balance;
    }

    public Account(int id, String name, long balance) {
        this.id = id;
        this.name = name;
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", balance=" + balance +
                '}';
    }
}

 

[ Controller ] 

package ch_01.day240216.mvc;

import java.util.ArrayList;
import java.util.Scanner;

// Controller
public class AccountManager {
    private ArrayList<Account> list;
    private Scanner stdIn;

    public AccountManager() {
        list = new ArrayList<>();
        stdIn = new Scanner(System.in);
    }

    public void makeAccount() { // 계좌 개설
        Account account = new Account();

        System.out.print("계좌 번호: ");
        account.setId(stdIn.nextInt());

        System.out.print("이름: ");
        account.setName(stdIn.next());

        System.out.print("입금액: ");
        account.setBalance(stdIn.nextLong());

        list.add(account);

        System.out.println("계좌가 개설되었습니다.");
        System.out.println(list.toString() + "\t");
    }

    public void deposit() { // 입금
        System.out.print("계좌번호: ");
        int id = stdIn.nextInt();

        System.out.print("입금액: ");
        long money = stdIn.nextLong();

        // 해당 계좌 찾기
        for (Account account : list) {
            if (account.getId() == id) { // 동일한 계좌가 있다면
                account.setBalance(money + account.getBalance());
                System.out.println("입금완료 되었습니다.");
                return;
            }
        }
        System.out.println("해당 계좌번호가 존재하지 않습니다.");
    }

    public void withdraw() { // 출금
        System.out.print("계좌번호: ");
        int id = stdIn.nextInt();

        System.out.print("출금액: ");
        long money = stdIn.nextLong();

        // 해당 계좌 찾기
        for (Account account : list) {
            if (account.getId() == id) { // 동일한 계좌가 있다면
                if (account.getBalance() < money) {
                    System.out.println("잔액이 부족합니다.");
                } else {
                    account.setBalance(account.getBalance() - money);
                    System.out.println("출금완료 되었습니다.");
                }
                return;
            }
        }
        System.out.println("해당 계좌번호가 존재하지 않습니다.");
    }

    public void inquire() { // 잔액 조회
        System.out.print("계좌번호: ");
        int id = stdIn.nextInt();

        // 해당 계좌 찾기
        for (Account account : list) {
            if (account.getId() == id) { // 동일한 계좌가 있다면
                System.out.println(account.getId() + "\t" + account.getName() + "\t" + account.getBalance());
                return;
            }
        }
        System.out.println("해당 계좌번호가 존재하지 않습니다.");
    }

    public void display() { // 출력
        for (Account account : list) {
            System.out.println(account.getId() + "\t" + account.getName() + "\t" + account.getBalance());
        }
    }
}

 

[ View ]

package ch_01.day240216.mvc;

import java.util.Scanner;

public class AccountView {
    public static void printMenu() {
        System.out.println("===========MENU===========");
        System.out.println("1. 계좌개설");
        System.out.println("2. 입금");
        System.out.println("3. 출금");
        System.out.println("4. 잔액조회");
        System.out.println("5. 전체출력");
        System.out.println("6. 프로그램종료");
        System.out.println();
    }

    public static void main(String[] args) {
        AccountManager manager = new AccountManager();
        Scanner stdIn = new Scanner(System.in);

        while (true) {
            printMenu();
            System.out.println("선택 : ");
            int choice = stdIn.nextInt();
            switch (choice){
                case 1:
                    manager.makeAccount();
                    break;
                case 2:
                    manager.deposit();
                    break;
                case 3:
                    manager.withdraw();
                    break;
                case 4:
                    System.out.println("계좌번호\t성명\t잔액");
                    manager.inquire();
                    break;
                case 5:
                    System.out.println("계좌번호\t성명\t금액");
                    manager.display();
                    break;
                case 6:
                    System.out.println("종료합니다.");
                    stdIn.close();
                    return;
                default:
                    System.out.println("잘못누르셨습니다.\n다시선택해주세요.");
                    break;
            }
        }
    }
}

 

8. MVC 패턴 + DB 연결

 - [ 디비 관련 코드 추가 ] > [ 데이터베이스에 account 테이블 추가 ]

# AccountManager.java
.
.
.

    public AccountManager() {
        getConnection();
        list = new ArrayList<>();
        stdIn = new Scanner(System.in);
    }

    // 디비 관련 시작
    private void getConnection() { // 디비 연결 생성자에서 실행
        try {
            String url = "jdbc:mariadb://localhost:3306/sample";
            String user = "root";
            String password = "5046";

            try {
                Class.forName("org.mariadb.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

            this.connection = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

.
.
.

 

[ makeAccount() list 주석 처리 > addAcount 추가 ] 

    public void makeAccount() { // 계좌 개설
        Account account = new Account();

        System.out.print("계좌 번호: ");
        account.setId(stdIn.nextInt());

        System.out.print("이름: ");
        account.setName(stdIn.next());

        System.out.print("입금액: ");
        account.setBalance(stdIn.nextLong());

//        list.add(account);

        System.out.println("계좌가 개설되었습니다.");
        System.out.println(list.toString() + "\t");
    }
    
    if(addAccount(account)) {
            System.out.println("계좌가 개설되었습니다.");
            System.out.println(list.toString() + "\t");
        } else {
            System.out.println("계좌 생성에 실패했습니다.");
        }
    }

 

[ isAccount, addAccount 메서드 추가 ]

    private boolean isAccount(int id) { // 동일한 계좌가 있는지
        int res = 0;
        try {
            String sql = "SELECT COUNT(*) AS cnt FROM account WHERE id = '" + id + "'";
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(sql);
            resultSet.next();
            res = resultSet.getInt("cnt");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res != 0 ? true : false;
    }

	private boolean addAccount(Account account) {
        /* 계좌 생성 */
        Statement statement = null;
        if (isAccount(account.getId())) { // 계좌 생성 전에 동일한 계좌 번호가 존재하는지 확인
            System.out.println(account.getId() + "계좌가 존재합니다.");
            return false;
        }

        boolean res = false;
        int cnt = 0;
        try {
            String sql = String.format("INSERT INTO account VALUES (%d, '%d', %d)",
                    account.getId(), account.getName(), account.getBalance());
            statement = connection.createStatement();
            cnt = statement.executeUpdate(sql);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (statement != null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        res = (cnt == 0) ? false : true;
        return res;
    }