[주요 내용] 데이터 베이스 프로그래밍

2024. 12. 11. 10:37데이터 분석/데이터 베이스 프로그래밍

1. JDBC의 개념

JDBC(Java Database Connectivity)는 Java 프로그램과 데이터베이스 간의 연결을 제공하는 표준 API입니다.

  • 데이터베이스와 독립적으로 설계되어, 다양한 DBMS(MySQL, Oracle, MS SQL 등)에서 동일한 코드로 데이터베이스 작업이 가능합니다.
  • 데이터베이스와 상호 작용하기 위해 JDBC 드라이버JDBC API를 사용합니다​(Lecture7-JDBC Programmi…).

2. JDBC의 구성요소

JDBC는 데이터베이스 연결과 작업을 지원하기 위해 다양한 인터페이스와 클래스를 제공합니다.

구성 요소설명

DriverManager DBMS 연결을 관리하는 클래스. JDBC 드라이버를 로드하고 연결을 생성합니다.
Connection 데이터베이스와의 연결을 나타내는 객체.
Statement SQL 문을 실행하기 위한 객체. executeQuery()와 executeUpdate() 메서드를 제공합니다.
PreparedStatement 미리 컴파일된 SQL 문을 실행하기 위한 객체. 매개변수를 바인딩하고 보안성을 제공합니다.
ResultSet SQL SELECT 질의 결과를 저장하는 객체.
DatabaseMetaData 데이터베이스에 대한 메타데이터를 제공하는 인터페이스.
ResultSetMetaData ResultSet 객체에 포함된 컬럼 정보와 메타데이터를 제공.

3. JDBC 사용방법(절차)

JDBC를 통해 데이터베이스와 상호 작용하기 위한 기본 절차는 다음과 같습니다​(Lecture7-JDBC Programmi…):

준비 단계

  1. JDBC 관련 패키지 임포트
import java.sql.*;

 

   2. JDBC 드라이버 로딩 및 등록

Class.forName("oracle.jdbc.driver.OracleDriver");

  3.  DBMS와의 연결(Connection 획득)

Connection conn = DriverManager.getConnection(url, user, password);

 

사용 단계

  4. SQL 문 실행을 위한 객체 생성

  • Statement
Statement stmt = conn.createStatement();
  • PreparedStatement
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM EMP WHERE DEPTNO = ?");
pstmt.setInt(1, 10);

   5. SQL 문 실행

  • SELECT
ResultSet rs = stmt.executeQuery("SELECT * FROM EMP");
  • INSERT, UPDATE, DELETE
int result = pstmt.executeUpdate();

   6. DBMS 응답 처리

while (rs.next()) {
    int empNo = rs.getInt("EMPNO");
    String empName = rs.getString("ENAME");
    System.out.println("EMPNO: " + empNo + ", ENAME: " + empName);
}

 

종료 단계

7. 자원 반납

  • 반드시 ResultSet, Statement, Connection 순으로 닫아야 합니다..
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();

4. Statement와 PreparedStatement의 차이

항목 Statement PreparedStatement
SQL 실행 방식 SQL 문을 실행할 때마다 컴파일. SQL 문을 미리 컴파일하여 실행.
매개변수 지원 지원하지 않음. SQL 문에 직접 값을 포함해야 함. 매개변수(?) 사용 가능.
보안성 SQL 인젝션에 취약. 매개변수 바인딩을 통해 SQL 인젝션 방지 가능.
성능 반복 실행 시 성능이 저하됨. 동일 SQL 문 반복 실행 시 더 효율적.
적합한 사용 사례 간단한 SQL 문을 한 번만 실행할 때. 매개변수가 많거나 반복 실행이 필요한 경우.
예제 코드 stmt.executeQuery("SELECT * FROM EMP
                             WHERE JOB = 'CLERK'");
pstmt.setString(1, "CLERK");
ResultSet rs = pstmt.executeQuery();

5. SQL 질의와 DML 실행을 위한 프로그램 코드의 구조 및 내용

SQL 질의 (SELECT) 실행 구조

  1. JDBC 드라이버 로딩 및 DB 연결.
  2. Statement 또는 PreparedStatement 객체 생성.
  3. executeQuery()를 사용해 SELECT 문 실행.
  4. ResultSet을 통해 결과 데이터 순회.
  5. 자원 반납.
String query = "SELECT EMPNO, ENAME FROM EMP WHERE DEPTNO = ?";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setInt(1, 10);
ResultSet rs = pstmt.executeQuery();

while (rs.next()) {
    int empNo = rs.getInt("EMPNO");
    String empName = rs.getString("ENAME");
    System.out.println("EMPNO: " + empNo + ", ENAME: " + empName);
}

DML 실행 (INSERT, UPDATE, DELETE) 구조

  1. JDBC 드라이버 로딩 및 DB 연결.
  2. PreparedStatement 객체 생성 및 매개변수 바인딩.
  3. executeUpdate()를 사용해 DML 실행.
  4. 영향을 받은 행 수 확인.
  5. 자원 반납.
String dml = "INSERT INTO EMP (EMPNO, ENAME, JOB, DEPTNO) VALUES (?, ?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(dml);
pstmt.setInt(1, 7950);
pstmt.setString(2, "Tom");
pstmt.setString(3, "Analyst");
pstmt.setInt(4, 20);
int result = pstmt.executeUpdate();
System.out.println("Affected rows: " + result);

구조적 차이

항목 SQL 질의 (SELECT) DML 실행 (INSERT, UPDATE, DELETE)
사용 메서드 executeQuery() executeUpdate()
결과 반환 ResultSet 객체 (조회된 데이터) 정수 값 (영향받은 행의 수)
적용 대상 데이터를 읽어오는 SELECT 문 데이터를 추가, 수정, 삭제하는 INSERT, UPDATE, DELETE 문

 

DAODTO

1. 계층 구조 (3-Tier Architecture)

애플리케이션을 3개의 계층으로 나누어 각 역할을 분리함:

  1. Presentation Layer (UI)
    • 사용자와 상호작용 (예: JSP, HTML).
    • 입력 데이터를 받아 Business Layer로 전달.
  2. Business Layer (서비스 계층)
    • 비즈니스 로직 수행.
    • 데이터를 처리하고 DAO를 호출하여 저장하거나 검색.
  3. Persistence Layer (데이터 계층)
    • 데이터 저장소(Database)와 상호작용.
    • DAO(Data Access Object)로 데이터 접근을 처리.

2. DAO (Data Access Object)

DAO는 Persistence Layer에서 데이터베이스 접근을 캡슐화하는 패턴.

  • 비즈니스 로직과 데이터 접근 로직을 분리하여 유지보수를 쉽게 함.

3. DAO의 구성요소

  1. DAO Interface
    • 데이터 삽입, 검색, 수정, 삭제 메서드를 정의.
    • 예: StudentDAO
  2. DAO Implementation
    • Interface를 구현해 데이터베이스 작업 처리.
    • 예: StudentDAOImpl
  3. DTO (Data Transfer Object)
    • 데이터를 계층 간 전송하기 위한 객체.
    • 예: StudentDTO에 학번, 이름, 학년 등의 정보 저장.
  4. Data Source
    • 데이터가 저장되는 장소 (Database, File System 등).

4. DAO의 장점

  • 데이터 저장소 독립성: 데이터베이스 변경 시 영향 최소화.
  • 비즈니스 로직 분리: 서비스와 데이터 접근 로직을 구분.
  • 재사용성: 데이터 접근 코드를 재활용 가능.
  • 유지보수 용이: 한 곳에서 데이터 접근 로직 관리.

간단 예제

StudentDAOImpl (데이터를 가져오는 DAO 클래스):

public class StudentDAOImpl implements StudentDAO {
    public List<StudentDTO> getStudentList() {
        String query = "SELECT STU_NO, STU_NAME FROM STUDENT";
        // 데이터베이스 접근 코드 수행 (생략)
        return new ArrayList<>();  // 학생 리스트 반환
    }
}

StudentServiceImpl (비즈니스 로직):

public class StudentServiceImpl implements StudentService {
    private StudentDAO dao = new StudentDAOImpl();
    public List<StudentDTO> getStudents() {
        return dao.getStudentList();  // DAO 호출
    }
}

JSP (화면 출력):

<c:forEach var="student" items="${studentList}">
    ${student.stuNo} ${student.stuName} <br>
</c:forEach>

MyBatis

 

  • 구조와 구성요소
    • mybatis-config.xml: 설정 파일 (DB 연결, Mapper 설정).
    • Mapper XML: SQL과 매핑 정의.
    • SqlSession: SQL 실행, 트랜잭션 관리.
  • 사용 방법
    1. mybatis-config.xml에 DB 연결 정보 작성.
    2. Mapper XML에 SQL 작성.
    3. SqlSession을 이용해 SQL 실행.
  • Mapper XML vs Interface
    • XML: 복잡한 동적 SQL 작성에 유리. / SQL ID를 문자열로 참조
    • Interface: 코드 간결, 타입 안전. / N:1,1:N 작성 제약
    • 병행 사용: XML에서 SQL 작성, Interface에서 메서드 호출.
  • SqlSession API
    • selectOne, insert, update, delete로 SQL 실행.
    • commit, rollback으로 트랜잭션 관리.
더보기
더보기
더보기

 

  • selectOne: 단일 결과 조회.
try (SqlSession session = sqlSessionFactory.openSession()) {
    User user = session.selectOne("mapper.UserMapper.getUserById", 1); // ID 1인 사용자 조회
    System.out.println("Username: " + user.getUsername());
}
  • selectList: 여러 결과 조회.
try (SqlSession session = sqlSessionFactory.openSession()) {
    List<User> users = session.selectList("mapper.UserMapper.getAllUsers"); // 모든 사용자 조회
    for (User user : users) {
        System.out.println("Username: " + user.getUsername());
    }
}
  • insert: 데이터 삽입.
try (SqlSession session = sqlSessionFactory.openSession()) {
    User newUser = new User();
    newUser.setUsername("new_user");
    newUser.setEmail("new_user@example.com");

    int rowsInserted = session.insert("mapper.UserMapper.insertUser", newUser);
    System.out.println("Rows inserted: " + rowsInserted);

    session.commit(); // 변경 사항 저장
}
  • update: 데이터 수정.
try (SqlSession session = sqlSessionFactory.openSession()) {
    User existingUser = new User();
    existingUser.setId(1); // 수정할 사용자 ID
    existingUser.setEmail("updated_email@example.com");

    int rowsUpdated = session.update("mapper.UserMapper.updateUser", existingUser);
    System.out.println("Rows updated: " + rowsUpdated);

    session.commit(); // 변경 사항 저장
}
  • delete: 데이터 삭제.
try (SqlSession session = sqlSessionFactory.openSession()) {
    int rowsDeleted = session.delete("mapper.UserMapper.deleteUser", 1); // ID 1 삭제
    System.out.println("Rows deleted: " + rowsDeleted);

    session.commit(); // 변경 사항 저장
}
  • commit/rollback: 트랜잭션 관리.
try (SqlSession session = sqlSessionFactory.openSession()) {
    try {
        // 데이터 삽입
        User newUser = new User();
        newUser.setUsername("temp_user");
        newUser.setEmail("temp_user@example.com");
        session.insert("mapper.UserMapper.insertUser", newUser);

        // 데이터 수정
        User existingUser = new User();
        existingUser.setId(1);
        existingUser.setEmail("rollback_email@example.com");
        session.update("mapper.UserMapper.updateUser", existingUser);

        // 트랜잭션 커밋
        session.commit();
        System.out.println("Transaction committed.");
    } catch (Exception e) {
        session.rollback(); // 에러 발생 시 롤백
        System.err.println("Transaction rolled back due to error.");
        e.printStackTrace();
    }
}

 

  • Mapper XML 매핑
    • Parameter Mapping: SQL에 값 전달.
    • Result Mapping: 결과를 객체에 매핑.
    • Complex Type/Collection: N:1 (<association>), 1:N (<collection>).
더보기
더보기
더보기

Mapper XML

<mapper namespace="mapper.CommentMapper">
  <resultMap id="commentResultMap" type="Comment">
    <id column="comment_id" property="commentId" />
    <result column="content" property="content" />
    <association property="user" javaType="User">
      <id column="user_id" property="userId" />
      <result column="username" property="username" />
      <result column="email" property="email" />
    </association>
  </resultMap>

  <select id="getCommentWithUser" parameterType="int" resultMap="commentResultMap">
    SELECT c.comment_id, c.content, u.user_id, u.username, u.email
    FROM Comments c JOIN Users u ON c.user_id = u.user_id
    WHERE c.comment_id = #{commentId};
  </select>
</mapper>
try (SqlSession session = sqlSessionFactory.openSession()) {
    CommentMapper mapper = session.getMapper(CommentMapper.class);

    // N:1 매핑
    Comment commentWithUser = mapper.getCommentWithUser(1);
    System.out.println("User: " + commentWithUser.getUser().getUsername());

    // 1:N 매핑
    Comment commentWithReplies = mapper.getCommentWithReplies(1);
    commentWithReplies.getReplies().forEach(reply -> System.out.println("Reply: " + reply.getContent()));
}

 


Transaction DBCP

1. 트랜잭션의 필요성

트랜잭션(Transaction)은 데이터베이스 작업에서 "All or Nothing" 방식으로 처리되는 논리적 작업 단위입니다. 여러 DML 문장을 묶어 작업 중 오류가 발생하면 모든 변경을 취소(rollback)하고, 성공하면 작업 결과를 확정(commit)합니다.

  • 필요성: 데이터 무결성과 안정성을 보장하기 위해, 특히 계좌 이체나 상품 주문 같은 작업에서 중간 오류로 데이터가 불일치하지 않도록 합니다.
  • ACID 속성: 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 영속성(Durability)을 만족해야 합니다.

주요 메서드:

  • setAutoCommit(boolean autoCommit): Auto-commit 설정/해제.
  • commit(): 트랜잭션 완료 및 결과 저장.
  • rollback(): 트랜잭션 취소 및 이전 상태로 복구.
conn.setAutoCommit(false); // Auto-commit 해제
try {
    // SQL 작업
    conn.commit(); // 성공 시 트랜잭션 확정
} catch (SQLException e) {
    conn.rollback(); // 실패 시 롤백
} finally {
    conn.setAutoCommit(true); // Auto-commit 재설정
}

3. DBCP(Database Connection Pool) 개념

DBCP는 데이터베이스 연결(Connection)을 효율적으로 관리하는 커넥션 풀링(Connection Pooling) 기술입니다.

  • 애플리케이션이 필요할 때 DB 연결을 미리 생성된 커넥션 풀(pool)에서 가져와 사용하고, 종료 시 다시 반환합니다.
  • 새로운 커넥션을 매번 생성·종료하지 않으므로 시스템 성능이 향상됩니다.

4. DBCP의 필요성

  • 성능 향상: DB 연결 생성·종료에 필요한 시간과 자원(CPU, 메모리)을 절약.
  • 자원 관리: 커넥션 수를 제한하여 시스템 부하 방지.
  • 재사용성: 유휴 상태의 커넥션을 유지해 재사용.

Apache Commons DBCP는 자주 사용하는 라이브러리로, 커넥션 풀을 쉽게 설정하고 관리할 수 있습니다.

DBCP 설정 예제:

BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
ds.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
ds.setUsername("scott");
ds.setPassword("tiger");
ds.setMaxTotal(10); // 최대 커넥션 수 설정

 

'데이터 분석 > 데이터 베이스 프로그래밍' 카테고리의 다른 글

[주요 문제] Transaction DBCP  (0) 2024.12.10
JDBC Programming  (0) 2024.11.03
[주요 내용] 문제 형식  (0) 2024.10.20