Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

rudu_std

JDBC 정리 본문

Java

JDBC 정리

Ru_Du 2024. 8. 2. 01:31
public class MemberDAO {
    private Connection con;         // DB 연결 객체
    private Statement stmt;         // 쿼리 (변수 포함 x) 실행 객체
    private PreparedStatement pstmt;// 쿼리 (변수 포함 O) 실행 객체 - 값을 ? 로 바인딩
    private ResultSet rs;           // 쿼리 실행 결과 레코드 집합 저장

    public MemberDAO() {this.con = DBCon.getConnection();}
    
    public MemberVO select(String id){
        String query = " SELECT * FROM t_member WHERE MID = ? ";
        MemberVO mvo = null;
        try { 
            pstmt = con.prepareStatement(query);
            pstmt.setString(1, id);    
            rs = pstmt.executeQuery();              

            if( rs.next()){
                mvo = new MemberVO();
                mvo.setMid(rs.getString("mid"));
                mvo.setMname(rs.getString("mname"));
                mvo.setMpw(rs.getString("mpw"));
                mvo.setEmail(rs.getString("email"));
                mvo.setGender(rs.getString("gender"));
                mvo.setPhoto(rs.getString("photo"));
                mvo.setBirth_date(rs.getString("birth_date"));
                mvo.setJoin_date(rs.getDate("join_date"));
                mvo.setAdministrator(rs.getString("administrator"));
            }
        } catch (SQLException e) throw new RuntimeException(e);
        } finally DBCon.close(rs, pstmt);
        return mvo;
    }

    public List<MemberVO> selectAll(){
        String query = " SELECT * FROM t_member ";

        List<MemberVO> list = new ArrayList<MemberVO>();

        try { // 쿼리문을 미리 준비
            pstmt = con.prepareStatement(query);
            rs = pstmt.executeQuery();                   

            while(rs.next()){
                MemberVO mvo = new MemberVO();
                mvo.setMid(rs.getString("mid"));
                mvo.setMname(rs.getString("mname"));
                mvo.setEmail(rs.getString("email"));
                mvo.setJoin_date(rs.getDate("join_date"));
                list.add(mvo);
            }
        } catch (SQLException e) throw new RuntimeException(e);
        } finally DBCon.close(rs, pstmt);
        return list;
    }
}

 

private Connection con;         // DB와 연결할 수 있게 이어주는 객체 

// DBCon 클래스는 데이터베이스 연결을 관리하기 위한 유틸리티 클래스입니다.
// 데이터베이스 연결을 생성하고 반환하는 기능을 제공합니다.
public class DBCon {

    // 1. 데이터베이스 연결 객체를 클래스 외부에서 접근할 수 없도록 선언
    // 이 객체는 데이터베이스 연결을 유지하고 관리합니다.
    private static Connection con; // DB 연결 객체
    private Statement stmt; // 쿼리 실행 객체 (사용되지 않지만 향후 쿼리 실행을 위한 확장 가능성)

    // 2. 기본 생성자를 선언하여 클래스 외부에서 접근할 수 없도록 처리
    // 외부에서 객체를 생성하지 못하도록 기본 생성자를 private으로 선언했습니다.
    private DBCon() {
        // 기본 생성자 - 이 클래스의 인스턴스 생성을 방지합니다.
    }

    // 3. 데이터베이스 연결 객체를 반환하는 메서드
    // 만약 Connection 객체가 null인 경우 새로운 객체를 생성하여 반환합니다.
    // 이미 연결이 존재하는 경우 기존 연결 객체를 반환합니다.
    public static Connection getConnection() {
        if (con == null) {
            // 데이터베이스 URL, 사용자 이름 및 비밀번호를 설정합니다.
            String url = "jdbc:mysql://localhost:3306/modeldb";
            String username = "username";   // MySQL 접속 계정
            String password = "password";   // MySQL 접속 비밀번호
            try {
                // DriverManager로 위 정보를 사용하여 데이터베이스에 연결합니다.
                con = DriverManager.getConnection(url, username, password);
                System.out.println("con ok"); // 연결 성공 시 메시지 출력
            } catch (SQLException e) {
                // 연결 실패 시 예외를 던집니다.
                throw new RuntimeException(e);
            }
        }
        return con; // 데이터베이스와 연결된 객체를 반환합니다.
    }
}


private Statement stmt;         // 변수가 필요없는 쿼리를 실행할때 사용하는 객체

executeUpdate  // 쿼리 실행 결과만 반환해준다

쿼리로인해 영향을 받은 행의 수를 정수 값으로 반환

예를들어 update로 2개의 행을 변경하면 executeUpdate는 2를 반환

전혀 영향을 주지 않았다면 0을 반환
잘못된 쿼리문은 SQLException 발생

	public void update(){
  
        String query = " UPDATE t_member SET EMAIL = 'bbb@bbb.com', PHOTO = 'bbb.png' WHERE MID = 'bbb' ";

        try (Statement stmt = con.createStatement()){// 쿼리 실행 객체 생성
            // try with resources이용 - 별도의 닫기 처리 불필요
            
            int result = stmt.executeUpdate(query);
            if(result == 1) System.out.println("update ok");
            else            System.out.println("update not ok");
        }catch (SQLException e){
            throw new RuntimeException(e);
        }
    }


private PreparedStatement pstmt;     // 변수가 필요한 쿼리를 실행할때 사용하는 객체

String query = " INSERT INTO t_member() VALUES( ?, ?, ?, ?, ?, ?, ?, now()) ";

pstmt = con.prepareStatement(query);

// 물음표의 순서대로 어디어 어떤 값이 들어갈지 입력(바인딩)한다
pstmt.setString(1, mvo.getMid());    
pstmt.setString(2, mvo.getMname());
pstmt.setString(3, mvo.getMpw());
pstmt.setString(4, mvo.getEmail());
pstmt.setString(5, mvo.getGender());
pstmt.setString(6, mvo.getPhoto());
pstmt.setString(7, mvo.getBirth_date());


private ResultSet rs;           // 쿼리 실행 결과가 다중행일경우 사용(단일행도 가능)

주로 DB에서 데이터를 조회하는 쿼리(SELECT)를 실행하는데 사용한다

executeQuery에 쿼리 결과를 담아오고

ResultSet을 통해 각 행의 데이터를 "순차적"으로 읽으며 처리한다

내부적으로 커서를 사용해 결과의 집합을 순회한다

executeQuery를 사용하면 ResultSet의 사용은 필연적이다

//////////        다중행         //////////

public List<MemberVO> selectAll(){
        // t_member 테이블의 모든 행 조회
        String query = " SELECT * FROM t_member ";

        List<MemberVO> list = new ArrayList<MemberVO>();

        try { // 쿼리문을 미리 준비
            pstmt = con.prepareStatement(query);
            rs = pstmt.executeQuery();   // 쿼리 실행 후 결과 받기
			//executeQuery에 결과 쿼리가 담겨있음
            while(rs.next()){
                // mvo 객체 생성 후 레코드 하나의 값들을 각 필드에 저장
                MemberVO mvo = new MemberVO();
                mvo.setMid(rs.getString("mid"));
                mvo.setMname(rs.getString("mname"));
                mvo.setEmail(rs.getString("email"));
                mvo.setJoin_date(rs.getDate("join_date"));
                //생성된 mvo 객체를 list에 저장
                list.add(mvo);
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBCon.close(rs, pstmt);
        }
        return list;
    }
    /////////////////////////////////////////////////////////////
    단일행
String query = "SELECT * FROM t_member WHERE mid = ?";
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1, "user123"); //첫번째 ?에 user123 을 넣음
ResultSet rs = pstmt.executeQuery();

if (rs.next()) {
    // ResultSet에서 데이터 읽기
    String id = rs.getString("mid");
    String name = rs.getString("mname");
    System.out.println("ID: " + id + ", Name: " + name);
}

 

 

finally 를 보면 늘 DBcon을 닫아주는데 그 이유는 다음과 같다

 

1. 리소스 관리

  • 데이터베이스 연결과 관련된 객체들은 시스템 자원을 사용한다. 특히, 연결이 지속적으로 열려 있으면, 서버의 리소스를 불필요하게 소비하여 성능 저하를 초래할 수 있다.
  • 자원을 올바르게 해제하지 않으면 메모리 누수가 발생할 수 있으며, 이는 장기적으로 서버 안정성에 악영향을 미칠 수 있다.

2. 데이터베이스 연결 제한

  • 많은 데이터베이스 시스템에는 동시 연결할 수 있는 연결의 수에 제한이 있다. 그러므로 연결을 제대로 닫지 않으면 사용 가능한 연결이 부족해져 새로운 연결을 만들 수 없게 된다.

3. 안전한 데이터 관리

  • 객체가 닫히지 않으면, 커밋되지 않은 트랜잭션이 계속 유지될 수 있다. 이는 데이터베이스 일관성에 문제를 일으킬 수 있다.
  • 또한, 리소스가 지속적으로 열려 있는 경우, 프로그램 종료 시 예상치 못한 오류가 발생할 수 있다.

4. 보안 문제

  • 열린 연결이 남아 있는 경우, 의도치 않은 데이터 노출이나 데이터 손상 위험이 증가할 수 있다. 닫지 않은 리소스는 잠재적인 보안 취약점을 초래할 수 있다.

JDBC Driver

1️⃣ DB에 맞는 JDBC Driver 로드

2️⃣ DB 서버의 IP, ID, PW 등을 이용하여 DriverManager 클래스의 getConnection() 메소드를 사용하여 Connection 객체 생성

3️⃣ sql문을 작성  Connection에서 PreparedStatement객체를 받음

4️⃣ executeQuery를 수행하고 ResultSet 객체를 받아 데이터를 처리

5️⃣ 사용하였던 ResultSet, PreparedStatement, Connection close()

 

 

 


[출처]

https://tussle.tistory.com/1039

'Java' 카테고리의 다른 글

Optional  (0) 2024.09.04
stream && Ramda  (0) 2024.09.03
JDBC  (0) 2024.08.01
람다 표현식 (Lambda Expression)  (0) 2024.07.24
클래스 형변환  (0) 2024.07.24