백엔드/JAVA

H2 데이터베이스 연결 (2)

두개의 문 2023. 5. 22. 23:54

( 지난 수업에 이어서 )

CRUD 구현

 
▷ 테이블 생성 및 데이터 추가 

package db.model;

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

public class H2ConnectionDemoApp {

	// JDBC_DRIVER
	static final String JDBC_DRIVER = "org.h2.Driver";
	// DB_URL
	static final String DB_URL = 
			"jdbc:h2:/Users/dahee/Desktop/app/database/h2/java2/:Users:dahee:;MODE=MariaDB;DATABASE_TO_UPPER=false";
	// DB_USER
	static final String USER = "";
	// DB_PASS
	static final String PASS = "";

	
	public static void main(String[] args) {
		// 연결 객체와 statement 객체 선언
		Connection conn = null;
		Statement stmt = null; // ctrl + shift + O -> import java.sql.Statement; 선택
		
		// DB연결 -> 예외 처리 ( try-catch-finally )
		try {
		// ① JDBC_DRIVER 연결 
			Class.forName(JDBC_DRIVER);
			pl("JDBC 드라이버 로딩 성공");
			
		// ② DB로 연결 생성
			pl("DB 서버로 연결중...");
			conn = DriverManager.getConnection(DB_URL, USER, PASS);
			pl("DB 서버에 접속 성공");
			
		// ③ SQL을 위한 객체 생성
			stmt = conn.createStatement();
			
		// ④ SQL 쿼리 문자열 작성 → Statement 객체가 DB서버로 전달
			String createSQL = 
					"DROP TABLE IF EXISTS member;"     +
					"CREATE TABLE member (" +
						"  id     INTEGER NOT NULL,  " +
						"  first  VARCHAR(100),      " +
						"  last   VARCHAR(100),      " +
						"  age    INTEGER,           " +
						"  PRIMARY KEY(id) " +
					");";
			
		// ⑤ SQL 질의 결과 반환
			stmt.executeUpdate(createSQL);
		// ------------- 이전 내용은 지난 시간과 동일 ------------- 	
			
			// < 1-1. 데이터 추가 > 
			// 1번 자료 추가 
			String insertSQL = "" +
					"INSERT INTO member " +
					"   ( id, first, last, age ) " +
					"    VALUES (" +
					"     101, 'Zara', 'ali', 18 ); ";
			stmt.executeUpdate( insertSQL );	
				
            		// 2번 자료 추가
			insertSQL = "" +
					"INSERT INTO member " +
					"   ( id, first, last, age ) " +
					"    VALUES (" +
					"     102, 'Mahnaxz', 'fatma', 25 ); ";
			stmt.executeUpdate( insertSQL );
				
            		// 3번 자료 추가
			insertSQL = "" +
				    "INSERT INTO member " +
					"   ( id, first, last, age ) " +
				    "    VALUES (" +
					"     103, 'Sumit', 'mittal', 28 );" ;
			stmt.executeUpdate( insertSQL );
			
			pl("############################################");
			pl("");
            
			// < 1-2. 입력된 결과 내용 가져오기 >
				// ① SELECT 구문 이용
			String selectSQL = 
				"""
					SELECT * FROM member
			
				""";	
			pl(selectSQL);
			ResultSet rs = stmt.executeQuery(selectSQL);
				
				// ② ResultSet으로부터 데이터 가져오기 
			while(rs.next()) {
				// ②-1. 가져온 레코드의 컬럼값을 가져오는 방법 
				// : getInt(필드명) - INTEGER | getString(필드명) - VARCHAR
				int id = rs.getInt("id");
				int age = rs.getInt("age");
				String first = rs.getString("first");
				String last = rs.getString("last");
			
				// ②-2. 화면에 출력
				p("ID : " + id);
				p(", Age : " + age);
				p(", First : " + first);
				pl(", Last : " + last);
			}
		
			// ③ 사용 후 종료
			rs.close();

		// ⑥ 다 사용했으면 종료하기 
			stmt.close();
			conn.close();
			
		// ⑦ 발생 가능성 있는 예외에 대한 처리
		} catch(SQLException se) {
			// SQLException cannot be resolved to a type
			// SQL예외가 나타나지 않았는데 적어놨다고 에러줄 뜬거니까 신경쓰지 않아도 됨
			// 불필요한 예외 만들지 말라는 뜻
			se.printStackTrace();
	
		} catch(Exception ex) {
			ex.printStackTrace();
			// 예외 발생 당시 호출스택에 있는 메서드의 정보 출력 및 에러메시지 출력
		} finally {
			// ⑧ 혹시 처리되지 못한 자원반납을 여기서 처리
			try {
				// ⑧-1. stmt가 제대로 종료되지 않았을 경우
				if(stmt != null) {
					stmt.close();
				}
			} catch(SQLException se) {
				// 최종 열림을 닫기 위한 구역이므로 
				// SQLException 예외 처리 안해도 됨
				se.printStackTrace();
			}
			
			try {
				// ⑧-2. conn가 제대로 종료되지 않았을 경우
				if(conn != null) {
					conn.close();
				}
			} catch(SQLException se) {
				se.printStackTrace();
			}
		}
	}

	// 로그함수 생성
	static void p(String msg) {
		System.out.print(msg);
	}
	static void pl(String msg) {
		p(msg + "\n");
	}
}

 

 

< 1-1. 데이터 추가 >

String insertSQL = "" +
            "INSERT INTO member " +
            "           ( id, first, last, age ) " +
            " VALUES " +
            " (101, 'Zara', 'ali', 18 ) ; ";
stmt.executeUpdate( insertSQL );

// 1 ~ 3번 자료 추가

 

 

< 1-2. 입력된 결과 내용 가져오기 >
① SELECT문 이용

String selectSQL =
                 """
                       SELECT * FROM member ;
                 """;
pl(selectSQL);
ResultSet rs = stmt.executeQuery(selectSQL);

- ResultSet 인터페이스 
  · SQL문에서 SELECT문을 사용한 질의의 경우, 성공 시 결과로 ResultSet을 반환 
    → ResultSet은 SQL 질의에 의해 생성된 테이블을 담고 있음
  · ResultSet 객체는 cursor를 갖고 있음 → cursor를 이용해 특정 행에 대해 참조함
  · 초기에 cursor는 첫번째 행의 직전(-1)을 가리키고 있음 → ResultSet 객체의 next( ) 메서드 이용해 다음 위치로 커서 이동 가능
  → 즉, ResultSet에서 반복문을 사용하여 next( ) 메서드가 유효한 행일 경우 true를 반환, 유효하지 않을 경우 false를 반환하여 데이터 가져올 수 있음
  ⇒ while문이 반복되면서 next( ) 메서드가 호출될 수록 한 줄씩 내려가면서 다음 행이 있는지 없는지 체크

 


 < 출력 결과 >


 
▷ 데이터 업데이트

			// < 2-1. 데이터 업데이트 >
			String updateSQL = 
					"""
						UPDATE member SET
						   age = 20,
						   first = 'Sara',
						   last = 'bil'
						WHERE 
						   id = 101;   
					""";
			stmt.executeUpdate(updateSQL);
			

			// < 2-2. 데이터 업데이트 후 부분 데이터 검색 >
			pl("\n데이터 업데이트 후 부분 데이터 검색\n");
			selectSQL = 
					"""
						SELECT * FROM member 
						   WHERE id = 101;
					""";
			pl(selectSQL);
			rs = stmt.executeQuery(selectSQL);
			
			while(rs.next()) {
				int id = rs.getInt("id");
				int age = rs.getInt("age");
				String first = rs.getString("first");
				String last = rs.getString("last");
				
				p("ID : " + id);
				p(", Age : " + age);
				p(", First : " + first);
				pl(", Last : " + last);
			}

 

 

 < 출력 결과 >


데이터 삭제

			// < 3-1. 데이터 삭제해보기 >
			String deleteSQL =
					"""
						DELETE FROM member
						   WHERE id = 101;
					""";
			pl(deleteSQL);
			stmt.executeUpdate(deleteSQL);
			// < 3-2. 데이터 삭제 후 삭제된 데이터 검색해보기 >
			pl("데이터 삭제 후 삭제된 데이터 검색\n");
			selectSQL =
					"""
						SELECT count(*) rows FROM member
							WHERE id != 101;
					""";
						// id = 101를 삭제했으므로 count = 2
						// count(컬럼명) : 모든 레코드(로우)의 수를 돌려줌
						// count(*) : delete한 결과 남은 레코드셋의 결과가 2가 됨 
						// WHERE id = 101 일 경우, 101번호는 삭제되었으므로
						// 결과는 0이 됨
			pl(selectSQL);
			rs = stmt.executeQuery(selectSQL);
				// rs의 결과 집합에 레코드가 있다는 이야기이므로
				// DELETE SQL 실행 실패

			if (rs.next()) {
				pl("row count = " + rs.getInt(1));
					// row count 는 레코드의 총 줄 수를 의미
					// rs.getInt(1) : 첫번째 컬럼 데이터 받아옴??????
			}

			rs.last();
			if( rs.getRow() > 0) {
				
				while (rs.next()) {
					
				}
			} else {
				// 레코드가 삭제되어 결과집합이 0인 경우
				pl("레코드가 삭제되었습니다.");
			}
- COUNT( ) 메서드 : 괄호 안의 항목의 개수를 카운트
 ① COUNT( * ) : null 값을 포함한 row 개수를 반환
 ② COUNT(1) = COUNT(*)의 결과와 동일
 ③ COUNT( column명 ) : null값을 제외한 row 개수를 반환

// rs.getRow(); -> 현재 rs의 첫번째 시작 record번호를 가르킴
//    마지막 레코드로 레코드 커서를 보냄
//    그렇게 하면 총 레코드 번호를 리턴함
//    (만일 비어있다면, 0이 될 것)
// rs.last();   ->  레코드 커서를 가장 마지막으로 이동시킴

 

 

< 출력 결과 >

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

데이터 입출력(1)  (0) 2023.05.30
JDBC 드라이버 다운로드 및 등록  (0) 2023.05.23
H2 데이터베이스 연결 (1)  (0) 2023.05.22
👉🏻 에러의 종류 및 에러 처리  (0) 2023.05.18
객체 지향 프로그래밍 이론(6)  (0) 2023.05.16