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

자바 - 19 (데이터베이스 연결)

by study_yeon 2023. 5. 25.

2023.05.24


● 복습

 

※ jdbc 설정법 요약
- 내가 사용할 드라이버 다운(확장자 jar)
- jar 파일 빌드패스 이용해서 모듈패스에 등록
- 고유의 통신방법이 있으므로 주소 알맞게 적기
- Class.forName() : 외부 라이브러리(드라이버) 불러오는 명령
- 예외에 대비(try-catch-finally)
- DriverManager.getConnection(jdbc주소, 사용자아이디, 사용자비밀번호) : 데이터베이스와 연결(서버와 연결)

-> connection 객체 생성
- ResultSet은 여러개라 루프를 돌림(값이 없으면 false가 리턴)

2023.05.23 - [백엔드/데이터베이스] - MySQL Workbench설치

 

MySQL Workbench설치

● MySQL Workbench설치 https://www.mysql.com/ MySQL Over 2000 ISVs, OEMs, and VARs rely on MySQL as their products' embedded database to make their applications, hardware and appliances more competitive, bring them to market faster, and lower their cost

dustj0824.tistory.com


○ 실습


* 클래스 MemberConnection, MemberApp

 

1. 워크밴치(또는 sts-mariadb)로 테이블 만들기

- 명령어 작성
* 컬럼4개, 데이터 5개 넣기
방법 1. 워크밴치 use java1;

use java1;
-- 테이블 생성create
create table member (
	id int not null,
    name varchar(20) not null,
    nick varchar(10) null,
    passwd varchar(20) not null,
    primary key(id, name)
);
-- 데이터 추가insert into
insert into member 
	(id, name, nick, passwd)
    values
    (101, 'java1', '자바', 'java1234');

-- 현재 레코드의 개수(확인용)
select count(*) 레코드수
	from member; 
-- 데이터 추가insert into
insert into member
	(id, name, nick, passwd)
	values
    (102, 'java2', '자바스크립트', 'java5678'),
    (103, 'java3', '리액트', 'java9012'),
	(104, 'java4', 'HTML', 'java3456'),
	(105, 'java5', '플러터', 'java7890');
    
-- 현재 레코드의 개수(확인용)
select count(*) 레코드수
	from member;


방법 2. sts에서 mariadb 연결하여 새sql 편집기로 작업
- 명령어는 워크벤치와 동일하게 작성

- 기존에 연결한 mariadb가 있으면 바로 편집기로 작업하기(연결은 1회만 해도 됨)

mariadb 연결

- 실무에서는 포트번호/ username 변경하여 위험에 대비하기
- dbear과 접속이 되면 데이터베이스 연결에 문제 없는 것을 확인하기 위한 좋은 방법 

jdbc:mariadb://{host}[:{port}]/[{database}]
- {} : 변수와 같은 개념
{host} : IP주소

2. sts에 라이브러리(드라이버) 연결

- 빌드패스를 통해 외부에서 만든 jar로 연결


※ 드라이버 라이브러리 다운로드 방법
1. mariadb 홈페이지에서 다운
다운로드 > connectors > 자바 선택(2.7.9) > 다운로드

2. maven repository 홈페이지에서 다운

- 기존에 다운받은 방법임

- 스프링과 적합


※ 참고

프로그램 흐름 : 순서도, UML
데이터의 흐름 : ERD

* ERD 

Entity Relationship Diagram
시스템 데이터들의 모임(테이블=엔티티)들의 상호관계를 나타내는 그래프 도형그림

- primary key로 참조
테이블과 테이블 사이는 외래키로 연결됨


● 실행클래스 작성 MemberApp 


* 작업 순서
1. pl("mariadb에 접속한다");
2. pl("member 테이블에 있는 데이터를 가져온다");
3. pl("가져온 레코드 집합을 화면에 보여준다");
4. pl("데이터베이스와 연결을 닫는다");
5. pl("--- fin ---");

 

1. mariadb에 접속한다

1) MemberConnection 클래스 만들기
- 데이터베이스 연결은 기본적으로 상수가 필요 : 기호상수 활용
- 커넥션변수 : mariadb와 연결상태를 유지해야함
- 생성자에서 마리아디비서버에 바로 연결
// Connection()은 db에 연결 성공하거나 실패하거나 -> 예외가 발생하니까 try-catch 사용
getConnection() - 인터페이스, 컨넥션 반환

 

※ 예외처리방법 

1-1) throws 던지기 
- 상위에서 처리하게 예외를 던짐
-> 사용자가 정의한 에러는 처리하지 못함

1-2) throw 사용자정의예외
- 런타임 / 일반적
- 예외를 상속해주기
- 커스터마이징하여 사용

1-3) try-catch로 직접처리

2) MemberApp으로 돌아와서

- 마리아디비서버와 연결할 연결객체 준비
- 데이터 추가하기 insert into 쿼리명령실행

- jdbc를 이용한 select쿼리 조회 (insert 작동 확인)


* 모델패턴
DAO : 데이터전문가
- 데이터와 데이터를 컨트롤하는 부분을 분리함
- 역할을 분리함으로써 컨넥션이 감춰짐
- 너무 많은 예외처리를 해결해줌
- DB서버와 연결됨
- DAO를 더 쪼개서 VO : 데이터를 읽어오는 것에 사용

DTO : 데이터 담는 클래스, 전송
- DAO안에 넣기
- 멤버, 속성함수, 생성자, toString, equals 등

 

* 자바의 영역
스택 : 메인 작업대
힙 : 작업대에서 필요한 데이터를 생성시키는 창고(= 운반대기소)


★ 회원관리 프로그램 만들기

 

● MemberConnection의 역할을 키우기(DB역할을 하는 DAO로 만들기)
- mariadb연결
- connection객체(+멤버변수)
- jdbc가 mariadb와 명령전달(statement 객체(+멤버변수) 소유)
- DML명령(insertSQL ...)
- 테이블 생성/삭제 메소드
- mariadb연결종료

package model.db;

import static model.util.MyIO.pl;

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

// Connection 객체
// 워크벤치에서 member 테이블 만들기
public class MemberConnection {
	// 데이터베이스 연결은 기본적으로 상수가 필요 : 기호상수 활용
	// 상수는 바로 초기화 해야함
	private static final String MARIADB_DRIVER = "org.mariadb.jdbc.Driver";
	private static final String JDBC_MARIADB_URL = "jdbc:mariadb://127.0.0.1:3306/java1";
	private static final String USER = "root";
	private static final String PASS = "mariadb";
	
	// 커넥션변수 : mariadb와 연결상태를 유지해야함
	private Connection conn;
	
	// 생성자에서 마리아디비서버에 바로 연결
	// Connection()은 db에 연결 성공하거나 실패하거나 -> 예외가 발생하니까 try-catch 사용
	public MemberConnection() {
		try {
			// 1. 드라이버에 연결
			Class.forName(MARIADB_DRIVER);
			pl("MARIADB 드라이버 가져오기 성공!");
			// 2. 드라이버를 이용해 실제 디비서버에 접속 -> 접속에 성공하면 멤버변수 conn에 보관
			conn = DriverManager.getConnection(JDBC_MARIADB_URL, USER, PASS);
			pl("MARIADB 서버연결 성공");
			
		} catch(Exception e) { 
			e.printStackTrace();
		}
	}
	
	// conn변수를 외부에 제공하는 getConnection()메소드 정의
	public Connection getConnection() {
		return conn;
	}
	
	// 마리아 디비 서버와 접속 끊기(순서 중요)
	public void close(Connection conn, Statement stmt, ResultSet rs) {
		// 데이터베이스 닫는 순서
		try {
			if (rs != null) {
			rs.close();
			}
			if (stmt != null) { 
			stmt.close();
			}
			if (conn != null) {
			conn.close();
			}
		} catch(SQLException se) {
			
		}
	}
	
	// conn만 닫아야함
	public void close() {
		try {
			if (conn != null) {
				conn.close();
			}
		} catch(SQLException se) {
			
		}
	}
	
	
}


* 디버그 중단점
Connection conn = null;

● main에 있는 insert into 쿼리명령실행을 메소드로 만들기 (나중에 분리하여 DAO가 됨)
-> 외부에서 불러와야하니까 static
stmt를 외부에서 값을 불러오기 - 내부에서는 실행만 하기 (코드의 간결성) 


-> 예외가 발생할 수 있어 에러가남 



기본자료형은 값을 복사를 한다
- 객체의 경우에는 같아짐

●SELECT 메소드로 만들기
- SELECT : 일렬로 나열된 자료 (배치)


● vo클래스 만들기
클래스 MemberVO

package model.db;

public class MemberVO {
	
	private int id;
	private String name;
	private String nick;
	private String passwd;
	
	// 생성자
	public MemberVO(int id, String name, String nick, String passwd) {
		this.id = id;
		this.name = name;
		this.nick = nick;
		this.passwd = passwd;
	}
	
	public void setId(int id) {
		this.id = id;
	}
	public int getId() {
		return this.id;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getName() {
		return this.name;
	}
	public void setNick(String nick) {
		this.nick = nick;
	}
	public String getNick() {
		return this.nick;
	}
	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public String getPasswd() {
		return this.passwd;
	}
}



● 컨트롤러 : 메뉴클래스 만들기
- 사실은 여기서부터 시작이 맞음
클래스 : MemberController 
목적 : 
1. 실질적인 Member관리클래스 MemberApp에서 이 객체를 생성하면 
2. 메뉴를 선택하여 MemberDAO객체를 생성하고 해당기능을 MemberDAO메소드를 호출함
3. 필요하면 MemberVO객체에 데이터를 추가하거나 MemberVO객체의 내용을 MariaDB에 보냄
4. 기본무한루프를 돌며 프로그램을 종료하기 전까지 선택한 메뉴를  실행합니다.

1. 멤버변수
1). 마리아디비와 상호작용할 모델객체(MemberDAO)
2). 간단히 키보드로부터 메뉴번호를 선택하기 위한 스캐너 클래스

3). 프로그램 실행

	/// 1. 마리아디비와 상호작용할 모델객체(MemberDAO)
	private MemberDAO memberDAO;
	/// 2. 간단히 키보드로부터 메뉴번호를 선택하기 위한 스캐너 클래스
	private Scanner sc;
	/// 3. 프로그램 실행중
	private boolean isRun;


2. 생성자
- 외부로부터 초기화할 내용이 필요 없으므로 메뉴를 불러내기 위한 MemberDAO와 Scanner 초기화 

	public MemberController() {
		memberDAO = new MemberDAO();
		sc = new Scanner(System.in);
		isRun = true;
	}


3. 기능메소드
1). 메뉴를 보여주는 기능 : showMenu()

	public void showMenu() {
		pl("회원관리 v0.1");
		pl("");
		pl("1. 목록");
		pl("2. 등록");
		pl("3. 수정");
		pl("4. 삭제");
		pl("5. 종료");
		pl("");
		pl("원하는 번호를 선택해주세요 : ");
	}


2). 메뉴를 선택실행하는 기능 : selectMenu()

	public void selectMenu() {
		int choice = sc.nextInt();
		switch(choice) {
		// 회원목록 가져오기
		case 1 : 
			memberDAO.getMemberList();
			break;
		// 회원추가
		case 2 : 
			memberDAO.insertMember();
			break;
		// 회원수정
		case 3 : 
			memberDAO.updateMember();
			break;
		// 회원삭제
		case 4 : 
			memberDAO.deleteMember();
			break;
		// 프로그램종료
		case 5 :
			isRun = false;
			break;
		}
	}


3). 메뉴를 계속 보여주는 무한루프 틀 : run()

	public void run() {
		// isEnd == false (끝이 아니다) | !isEnd == !false (끝)
		while(isRun == true) {
			showMenu();
			selectMenu();
		}
		// isRun == false : 프로그램종료
		sc.close();
	}


● 실행클래스 만들기

MemberManagerApp

1. MemberController 객체 생셩
2. MemberController 객체의 run()실행 : 관리메뉴 출력

package model.app;
import model.controller.MemberController;
public class MemberManagerApp {

	public static void main(String[] args) {
		MemberController memberController = new MemberController();
		memberController.run(); // 회원관리 메뉴시작		
	}
}

 


※ 의문점 
1. 커넥션클래스에서도 닫고 앱에서도 닫는 이유는? (코드 수정)
- 커넥션이 실질적으로 데이터베이스와 접속이 이루어지는 부분이므로 이곳에서 끊어주는게 맞다
- 그러나 안정성을 위해 한번 더 닫아주는 작업을 할 수 있다-> 앱에서는 없어도 된다는 것

* 참고) 우리가 만든 객체를 닫아줘야함(conn은 참조할 뿐) 

- main()의 conn객체는 java.sql.Connection클래스 형식이므로 MemberConnection클래스의 Connection과는 직접 관련이 없고 단지 참조주소를 가르킨다.
- 따라서 memberConn.close()함수를 호출하면 main()의 conn변수의 참조주소도 null로 바뀐다.

2. 로컬호스트를 다시 부른 이유는?
- 그냥 하는 방법을 다시 알려주기 위함(sts db목록에서 삭제해도 실제 데이터가 사라지지는 않음)

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

자바 - 21 (노래 관리 프로그램 분리하기)  (0) 2023.05.31
자바 - 20 (노래 관리 프로그램 만들기)  (0) 2023.05.25
자바 - 18 (데이터베이스 연결)  (0) 2023.05.22
자바 - 17  (0) 2023.05.21
자바 - 16  (0) 2023.05.19