본문 바로가기
백엔드/자바

자바 - 20 (노래 관리 프로그램 만들기)

by study_yeon 2023. 5. 25.

2023.05.25

● 복습


* mvc역할 
model

- 데이터를 가진 객체

- DAO(DB와 소통) DTO(속성함수?) VO(뷰로부터 입력받은 데이터)
1. 사용자가 편집하길 원하는 모든 데이터를 가지고 있어야만 함
2. 뷰나 컨트롤러에 대해서 어떠한 정보도 알지 말아야 함
3. 변경이 일어나면, 변경 통지에 대한 처리방법을 구현해야 함

 

controller

- Controller는 Model과 View 사이를 이어주는 인터페이스 역할.
즉, Model이 데이터를 어떻게 처리할지 알려주는 역할 

- 사용자는 컨트롤러를 사용하여 모델의 상태를 바꾼다. 

- 라우팅, 요청을 받으면 요청을 분할
- > 너무 복잡하면 서비스(라우팅 요소의 처리) 부분이 별도로 분리되기도 함
1. 모델이냐 뷰에 대해서 알고 있어야 함
2. 모델이나 뷰의 변경을 모니터링해야 함


view

- 메뉴역할, 화면(데이터 및 객체)입출력 담당
- 뷰는 보여줄 값(모델)을 컨트롤러로부터 받아와 사용자에게 보여준다.
1. 모델이 가지고 있는 정보를 따로 저장해서는 안됨
2. 모델이나 컨트롤러와 같이 다른 구성 요소를 몰라야 함
3. 변경이 일어나면, 변경 통지에 대한 처리방법을 구현해야 함

 

* 메인(실행클래스) 처음으로 객체를 불러냄


* 기호상수는 선언부터 바로 존재함
- static으로 만들기
- enum 클래스로 분리하기도 함

* 로그로 기록을 남김


● 노래관리프로그램 만들기

※ 패키지 설계(패키지에 들어갈 파일, 기능 등 구상해두기)


▶ 패키지 만들기

* song.domain

- 모델(특정기능을 담당)
* song.app

- 실행클래스

- 함수 호출
* song.manage

- DB관리
* song.util

- 단축어 등



▶ 클래스 만들기

 

MyIO 
- 유틸클래스

 

SongManageApp
- 실행클래스 

package song.app;
import song.magage.*;
public class SongManageApp {
	
	public static void main(String[] args) {
		// 노래관리 클래스 출연
		SongManager songManager = new SongManager(); // import 하기
		songManager.run();
	}
}

- songManager객체는 메뉴를 출력 / 선택 / 선택한 기능 처리를 반복
+ 종료를 선택하면 프로그램을 빠져나옴
- 메뉴를 화면에 보여주는 작업 : songManager.run()
-> run에 showTitle(), showMenu(),choiceMenuItem() ,doMenuItem()가 포함


SongDAO 
- 처음에 클래스만 만들고 틀 작성 후 상세내용 작성하며 내용 추가

 

1) 멤버변수

	Connection conn; // 데이터베이스에 연결하는 연결객체
	Statement stmt;  // conn을 통해 SQL명령을 실행하고 결과를 받아오는 역할을 하는 운송객체
	PreparedStatement prestmt; // Statement를 확장하여 속도가 빠르고 SQL Injection공격을 방어할 수 있다
	ResultSet rs;

2) 생성자 : 데이터베이스와 연결객체 생성

	public SongDAO() {
		// 데이터베이스와 연결안된 상태로 시작
		conn = null;
		stmt = null;
		prestmt = null;
		rs = null;		
	}

3) 기능메소드

	// 기능메소드 
 	// insertSong() : 연결객체를 통해서 테이블에 데이터 추가
	@Override
	public void insertSong() {
		
	}
	// updateSong() : 연결객체를 통해서 레코드 수정
	@Override
	public void updateSong() {
		
	}
	// deleteSong() : 연결객체를 통해서 레코드 삭제
	@Override
	public void deleteSong() {
		
	}
	// selectSong() : 연결객체에 원하는 노래정보 레코드를 가져옴
	@Override
	public void selecteSong() {
		
	}
	// getConnection() : 생성된 연결객체를 가져오는 속성함수
	@Override
	public void getConnection() {
		
	}
	// close() : 데이터베이스 연결 종료
	@Override
	public void close() {
		
	}
}


SongManager
- DAO를 직원으로 두어 DB관리
- user가 입력하는 기능 처리
- 메뉴 출력 / 메뉴 선택 
- 선택한 메뉴 처리기능
* 메뉴 구성 : 목록 입력 삭제 마침

1) 멤버변수

SongDAO songDAO; // 데이터베이스와 상호작용하는 클래스
Scanner sc; 
int choiceMenuItem;  // 사용자가 키보드로부터 선택한 메뉴번호 저장장소
boolean isRunLoop;

2) 생성자(멤버변수의 초기화)

	public SongManager() { // 인수가 없는 기본생성자
		songDAO = new SongDAO();  // 데이터베이스 연결
		sc = new Scanner(System.in);
		choiceMenuItem = -1;  // 메뉴가 선택되지 않았다(메뉴가 양수로 구성이 되어있으니 -1)
		isRunLoop = true;  // 매뉴 루프 진행중
		
	}

3) 기능

	public void showTitle() {
		pl("--- 노래관리 프로그램 v0.1 ---");
	}
	public void showMenu() {
		pl("");
		pl(" 1. 노래 목록 보기");
		pl(" 2. 노래 정보 입력");
		pl(" 3. 노래 정보 삭제");
		pl("--------------");
		pl(" 0. 프로그램 종료");
	}
	
	public void choiceMenuItem() {
		pl("");
		p("메뉴 번호를 선택해주세요 : ");
		this.choiceMenuItem = sc.nextInt();
	}
	
	public void doMenuItem() {
//		pl("선택한 메뉴를 실행합니다."); // 로그(나중에 지워도 됨)
		songDAO.getConnection();
		switch(this.choiceMenuItem) {
		case 1 : 
//			pl("doMenuItem() -> 노래 목록을 출력합니다."); // 로그(이 출력이 어디서 나왔는지 알기위함)
			songDAO.selecteSong();
			break;
		case 2 : 
//			pl("doMenuItem() -> 노래 정보 추가");
			songDAO.insertSong();
			break;
		case 3 :
//			pl("doMenuItem() -> 노래 삭제");
			songDAO.deleteSong();
			break;
		case 0 : 
//			pl("doMenuItem() -> 프로그램 종료");
			songDAO.close();
			isRunLoop = false; // doMenuItem > while 루프 종료
			break;
		default : 
			pl("잘못된 메뉴를 선택하셨습니다.");
			break;
		}
	}
// 노래관리 메뉴 무한루프
	public void run() {
		while(isRunLoop == true) {
			// 프로그램 제목을 출력합니다.
			showTitle();
			// 메뉴를 출력합니다.
			showMenu();
			// 메뉴를 선택합니다.
			choiceMenuItem();
			// 선택한 메뉴를 실행 합니다.
			doMenuItem();
		}
		pl("--- 프로그램 마침 ---");
	}



* 디버그 
- 중단점 songManager.run(); 

* 로그(이 출력이 어디서 나왔는지 알기위함)
- 객체명.함수명()을 적음


▶ 데이터베이스 입력


* 어떤 데이터베이스를 사용할지 결정(h2, 오라클, MariaDB 등)
- MariaDB 사용

1. 데이터베이스 만들기(muse)
방법 1) sql 명령이용
create database muse;
create schema muse;
-> 같은 기능
방법 2) Databases 오른쪽마우스 > create database

2. Refresh 하여 생성 확인

3. 테이블 만들기
- 데이터베이스 오류 (저장될 자리를 찾을 수 없음) 

-> use 데이터베이스명; 을 실행하면 오류 해결

create schema muse;

use muse; -- 데이터베이스 muse를 사용하겠다

drop table if exists song;  -- 현재 지정한 테이블이 있으면 삭제

-- 데이터베이스명.테이블명 : 데이터베이스 밑의 테이블
-- 식별자(변수, 컬럼명, 테이블명 등) 구분기호가 기본값이 `식별자명`
create table muse.song(
	song_id      int not null,
	song_name    varchar(100) not null,
	song_content varchar(1000), -- 생략은 null
	singer       varchar(20),
	primary key (song_id)
); 

-- 데이터 집어넣기(insert into)
use java1; -- 현재 작업 데이터베이스를 바꾼다
-- 표준 SQL insert 구문
insert into `muse`.`song` -- 데이터베이스 muse의 테이블 song에 데이터 넣겠다
	(song_id, song_name, song_content, singer)
	values
	(101, '인연', '왕의남자 대표곡', '이선희');
-- mariadb 간단 확장 멀티입력기능
insert into muse.song
	(song_id, song_name, song_content, singer)
	values
	(102, '떠날 수 없는 당신', '', '박지현'),
	(103, '손오공', '', '세븐틴'),
	(104, 'KONCK', '', '이채연'),
	(105, '캔디', '', '박재범');
	
-- 데이터 확인
select * from 
	muse.song;

존재하지 않음 오류

- java1이라는 데이터베이스에는 song이라는 테이블이 없어서 오류가 생김

-> use java1을 하여도 명령어에 insert into `muse`.`song와 같이 데이터베이스를 명시해주면 됨

 

※ mysql oracle 등 대형서버의 작업순서
1) 사용자 계정을 만든다
2) 데이터베이스를 선택한다 - use 데이터베이스명;
3) 그 데이터베이스에서 작업한다

* utf8 설정
- 언어 깨지는 문제가 발생하지 않음


▶ 자바 DAO 작성


※ DAO
- Data Access Object 의 약자로 데이터베이스의 data에 접근하기 위한 객체
- DataBase 접근을 하기 위한 로직과 비지니스 로직을 분리하기 위해 사용
- DAO의 경우는 DB와 연결할 Connection 까지 설정되어 있기도 함

▷ SongDAO 클래스 작업
1. DML 4대명령(insert, delete, update, select)등 기능을 인터페이스로 분리하여 다중상속 받기

- 필수로 구현해야한다는 것을 이용하여 프로그램의 안정성을 확보

- 호환성 보장
-> 하나의 인터페이스로 만들어도 되지만 다중상속을 보여주기 위해 수업에서는 분리

package song.domain;

public interface Connectionable {
	void getConnection();
	void close();
}

- 4대명령도 동일한 양식으로 인터페이스 만들기

public class SongDAO 
		implements 
			Connectionable, Insertable, Updatable, Deletable, Selectable{
                
}

-> 인터페이스를 상속받았으면 구현해주어야함

 

2. 멤버변수

Connection conn; // 데이터베이스에 연결하는 연결객체
Statement stmt;  // conn을 통해 SQL명령을 실행하고 결과를 받아오는 역할을 하는 운송객체
PreparedStatement prestmt; // Statement를 확장하여 속도가 빠르고 SQL Injection공격을 방어할 수 있다
ResultSet rs;


3. 생성자 : 데이터베이스와 연결객체 생성

public SongDAO() {
// 데이터베이스와 연결안된 상태로 시작
	conn = null;
	stmt = null;
	prestmt = null;
	rs = null;		
}


4. 기능메소드 
insertSong() : 연결객체를 통해서 테이블에 데이터 추가
updateSong() : 연결객체를 통해서 레코드 수정
deleteSong() : 연결객체를 통해서 레코드 삭제
selectSong() : 연결객체에 원하는 노래정보 레코드를 가져옴
getConnection() : 생성된 연결객체를 가져오는 속성함수
close() : 데이터베이스 연결 종료

@Override
public void insertSong() {
}
@Override
public void updateSong() {
}
@Override
public void deleteSong() {
}
@Override
public void selecteSong() {
}
@Override
public void getConnection() {
}
@Override
public void close() {
}


---구체적 기능 넣기---

* song 클래스 만들기
- 데이터베이스의 레코드와 대응함


● 하나의 클래스에 담기

 

▶ SongDAOMemoApp 클래스 만들기

 

▷ main()  - 시작부분으로 함수 호출

- getConnection()을 호출하여 마리아디비 서버에 연결

- 처리 후 디비 닫기

public static void main(String[] args) {
	// getConnection()을 호출하여 마리아디비 서버에 연결
	Connection con = getConnection();
		
	// 복잡한 비즈니스 로직 처리
	// 처리 후 DB연결 닫기
	// 연결된 연결객체 conn을 close 메소드로 닫기
	close(con);
		
	}

▷ 메소드 getConnection() - 디비와 연결해서 연결객체를 만들어 반환

	public static Connection getConnection() {
		// 실행되기전에 반드시 초기화(0에 가까운 값) 해야함
		Connection conn = null; // 캡슐화
		
		// 디비작업은 예외가정
		try {
			String db_driver_name = "org.mariadb.jdbc.Driver";
			// 해당 이름의 라이브러리가 있는지 검사
			// 라이브러리가 있으면 메모리로 실행코드 로딩
			Class.forName(db_driver_name);
			// DB 드라이버가 있다면 디비서버로 연결 | 없으면 SQL 예외처리
			// 프로티콜 구분기호는 항상 ://
			// 127.0.0.1은 로컬네트워크 주소
			String jdbc_url = "jdbc:mariadb://localhost:3306/muse";
			String user = "root";
			String passwd = "mariadb";
			
			conn = DriverManager.getConnection(jdbc_url, user, passwd);
			
		} catch(SQLException se) {
			
		} catch(Exception e) {
			// 배우는 중이므로 어떤 에러가 나는지 확인
			e.printStackTrace();
		}
		
		return conn; // 참조변수라서 객체의 주소를 넘김
		
	}

 

※ 초기화 기본타입
정수 : 0
실수 : 0.0
boolean : false
문자 : '\u0000'
객체 : null

* 자바의 규칙
객체는 힙에 생성
객체는 참조변수
- 참조: 원본을 준다
참조하는 변수의 내용을 바꾸면 원본의 내용이 변경됨

SongDAOMemoApp
main()이 getConnection를 호출
- 실행결과 결과값으로 conn변수가 나옴

getConnection은 Connection의 conn이라는 변수를 가짐 -> mariadb와 연결
- return conn; -> 컨넥션객체의 주소를 변수이름(conn)으로 리턴

메인의 참조변수와 메소드(메인 밖)의 참조변수가 다른 이름을 가져도 같은 힙의 주소를 가르키면
매소드가 종료되어도 메인이 가르키고 있기 때문에 힙의 객체는 사라지지 않는다 메인까지 종료되면 가비지콜랙터에 의해 사라진다

 

▷ 자원반납 - 닫기

	public static void close(Statement stmt, Connection conn) {
		// stmt 닫기
		try {
			stmt.close();
		} catch (SQLException se) {
			se.printStackTrace();
		} 	
		// conn 닫기
		try {
			conn.close();
		} catch (SQLException se) {
			se.printStackTrace();
		} 
	}
	
	public static void close(Connection conn) {
		try {
			conn.close();
		} catch (SQLException se) {
			se.printStackTrace();
		} finally {
			try {
				if (conn != null) {	
					conn.close();
				}
			} catch (SQLException se) {
			
			}
		}
	}





 

'백엔드 > 자바' 카테고리의 다른 글

자바 - 22 (List - 리스트)  (0) 2023.05.31
자바 - 21 (노래 관리 프로그램 분리하기)  (0) 2023.05.31
자바 - 19 (데이터베이스 연결)  (0) 2023.05.25
자바 - 18 (데이터베이스 연결)  (0) 2023.05.22
자바 - 17  (0) 2023.05.21