DB 접근/JDBC (Java Database Connectivity)

[ORM] JDBC

JABHACK 2024. 12. 23. 18:00

JDBC

📌 Java 언어를 사용하여 DB와 상호 작용하기 위한 자바 표준 인터페이스로 데이터베이스 관리 시스템(DBMS)과 통신하여 데이터를 삽입(C), 검색(R) , 수정(U) 및 삭제(D)할 수 있게 해준다.

 

JDBC 구조

JDBC의 주요 특징

  1. 표준 API
    1. 대부분의 RDBMS (관계형 데이터베이스 관리 시스템)에 대한 드라이버가 제공되어 여러 종류의 DB 대해 일관된 방식으로 상호 작용할 수 있다.
    ex) Database 종류가 바뀌어도 쿼리문이 실행된다. MySQL → ORACLE
  2. 데이터베이스 연결
  3. SQL 쿼리 실행
  4. Prepared Statement
  5. 결과 집합 처리(Result Set)
    • 데이터베이스로부터 반환된 결과 집합을 처리할 수 있다.
    ex) 데이터를 조회하고 결과를 Java 객체로 매핑할 수 있다.
  6. 트랜잭션 관리
    • JDBC를 사용하여 데이터베이스 트랜잭션을 시작, 커밋(성공) 또는 롤백(실패)하는 등의 트랜잭션 관리 작업을 수행할 수 있습니다.

 

JDBC의 주요 구성 요소

  1. DriverManager:
    • 데이터베이스 드라이버를 관리하고, 데이터베이스 연결(Connection)을 제공합니다.
  2. Connection:
    • 데이터베이스와 애플리케이션 간의 연결을 나타냅니다.
  3. Statement:
    • SQL 문을 실행하는 데 사용됩니다. (예: Statement, PreparedStatement, CallableStatement)
  4. ResultSet:
    • SQL 쿼리 결과를 저장하고 처리하는 객체.
  5. SQLException:
    • 데이터베이스 작업 중 발생하는 예외를 처리하는 클래스.

 

JDBC 작동 원리

  1. 애플리케이션이 JDBC API를 호출합니다.
  2. DriverManager가 요청을 적절한 데이터베이스 드라이버에 전달합니다.
  3. 데이터베이스 드라이버가 데이터베이스에 연결을 설정합니다.
  4. Connection 객체를 통해 SQL 문을 실행하고 결과를 반환받습니다.

 

 

JDBC를 사용하는 단계

a. 데이터베이스 드라이버 로드

  • 데이터베이스와 상호작용하기 위해 드라이버를 메모리에 로드
Class.forName("com.mysql.cj.jdbc.Driver");

 

b. 데이터베이스 연결

  • DriverManager를 사용하여 데이터베이스에 연결.
Connection connection = DriverManager.getConnection(
    "jdbc:mysql://localhost:3306/mydatabase", "username", "password"
);

c. SQL 문 실행

  • Statement 또는 PreparedStatement를 사용하여 SQL 문 실행.
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");

d. 결과 처리

  • ResultSet 객체를 사용하여 쿼리 결과를 읽고 처리.
while (resultSet.next()) {
    System.out.println("ID: " + resultSet.getInt("id"));
    System.out.println("Name: " + resultSet.getString("name"));
}

e. 자원 해제

  • 사용한 자원(Connection, Statement, ResultSet)을 닫아야 함.
 
resultSet.close();
statement.close();
connection.close();

 

 

 

Statement VS Prepared Statement

📌 Java에서 데이터베이스에 SQL 쿼리를 실행하기 위한 인터페이스이다. 이들은 데이터베이스와의 통신을 통해 쿼리 결과를 반환하거나 데이터 조작을 수행하는 데 사용됩니다.

 

Statement

  • DB와 연결되어 있는 Connection 객체를 통해 SQL문을 Database에 전달하여 실행하고, 결과를 반환받는 객체
public class StatementExample {
    public static void main(String[] args) {
        try {
						// MySqlDriver 파일을 라이브러리에 추가한다.
						
						// Driver연결
						Class.forName("mysql.jdbc.driver.MySqlDriver");
						
						// Database와 연결(계정 접속)
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase", "username", "password");
            
						// Statement 인스턴스 생성
						Statement statement = connection.createStatement();
            
						// String SQL Query
						
            String query = "SELECT * FROM MEMBER WHERE NAME = 'wonuk'";
            
						// Query 실행 -> 결과는 ResultSet으로 반환된다.
						ResultSet rs = statement.execute(query);
            
            // 결과 처리
						while (rs.next()) {
							// 결과 처리 로직
						}
            
						// 연결을 수동으로 끊어줘야한다.
						rs.close();
            statement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  • SQL 쿼리를 직접 문자열로 작성하여 데이터베이스에 보내는 방법이다.
  • SQL 쿼리는 실행 전에 문자열 형태로 전달되고, 실행 시점에 데이터베이스에 직접 파싱되고 실행.
  • 매번 실행할 때마다 SQL 문을 다시 파싱하므로 성능에 영향을 미칠 수 있고, 보안 취약점을 가질 수 있습니다.

 

 

Prepared Statement

  • SQL문을 Complie 단계에서 ? 를 사용하여 preCompile 하여 미리 준비해놓고 Query문을 파라미터 바인딩 후 실행하고 결과를 반환받는다. 미리 준비해놓았다(Pre) 중요!
public class PreparedStatementExample {
    public static void main(String[] args) {
        try {
						// [Mysql.jdbc.driver.MysqlDriver] 파일을 라이브러리에 추가한다.
						Class.forName("mysql.jdbc.driver.MysqlDriver");
						
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase", "username", "password");
            String query = "SELECT * FROM employees WHERE department = ?";
            PreparedStatement preparedStatement = connection.prepareStatement(query);
            
            // 값을 설정
            preparedStatement.setString(1, "HR");
             
            ResultSet resultSet = preparedStatement.executeQuery();
            
            while (resultSet.next()) {
                // 결과 처리 코드
            }
            
            resultSet.close();
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  • SQL 쿼리를 미리 컴파일하여 데이터베이스에 전송할 때 값만 바뀌는 형태로 전달한다.
  • 쿼리가 한 번 컴파일되면 여러 번 실행할 수 있으며, 성능이 향상되고 보안 측면에서 더 안전한다.
  • 동적인 입력값을 placeholder?로 대체하고 파라미터 바인딩을 통해 쿼리를 삽인한다. 즉, 사용자 입력을 직접적으로 쿼리에 삽입하지 않는다.
  • 이스케이핑 처리를 지원한다. 말그대로 탈출(Escape), 입력값이 자동으로 쿼리에 안전하게 이스케이핑된다. 이스케이핑은 입력 데이터에서 잠재적인 SQL 쿼리 문자열을 무력화한다.

 

 

SQL Injection

📌 악의적인 사용자가 애플리케이션에서 입력 데이터를 이용하여 SQL 쿼리를 조작하고 데이터베이스에 무단 접근하거나 데이터를 변조하는 공격이다.

 

 

SQL Injection 종류

  1. Error Based SQL Injection
    1. Database에 고의적으로 오류를 발생시켜 에러 응답을 통해 DB 구조를 파악하는 방법.
  2. Union Based SQL Injection
    1. 컬럼의 개수와 데이터 형식이 같아야 한다.
    2. DB의 UNION 연산자를 사용하여 쿼리 결과값의 조합을 통해 정보를 조회한다.
  3. Blind Based SQL Injection
  4. Stored Procedure SQL Injection
  5. Time Based SQL Injection
  • SQL Injection 예시

  • Java 코드 예시
// 로그인
public String login(String id, String password) {
		return String query = 
			"SELECT * FROM MEMBER WHERE ID = " + id
			+ "AND PASSWORD = " + password;
}

// 검증
public String login(String id, String password) {

			// 매개변수 id, password 가 문제없는지 검증하는 로직 Escape 등
			
			String query = 
			"SELECT * FROM MEMBER WHERE ID = " + id + "AND PASSWORD = " + password;
			return query;
}
  • 해결방법
    • 클라이언트에게 에러 메세지 노출을 차단한다.
    • 입력값을 검증(Validation)한다.
    • Prepared Statements를 사용한다.

 

XSS(Cross Site Scription)

📌 악성 스크립트를 웹사이트에 주입하는 Code Injection 기법 중 하나. 웹 애플리케이션에서 발생하는 보안 취약점으로, 공격자가 악성 스크립트를 사용자 브라우저에서 실행하도록 유도하는 공격입니다.

  • 이를 통해 공격자는 사용자의 세션 쿠키를 탈취하거나, 악성 코드를 실행해 개인 정보를 노출시키고, 웹사이트의 신뢰성을 훼손할 수 있습니다.

XSS의 동작 원리

  • 공격자가 웹 애플리케이션의 취약점을 이용해 악성 스크립트를 삽입.
  • 사용자가 해당 페이지를 열거나 입력값을 처리할 때 악성 스크립트가 실행됨.
  • 브라우저는 이 스크립트를 신뢰된 사이트의 일부로 간주하여 실행.

 

XSS의 위험성

  1. 세션 탈취:
    • 사용자의 세션 쿠키를 탈취하여 계정에 접근.
  2. 웹사이트 변조:
    • 사용자 브라우저에서 악성 콘텐츠를 표시하거나, 위조된 페이지를 로드.
  3. 피싱 공격:
    • 사용자에게 신뢰할 수 없는 링크를 클릭하도록 유도.
  4. 브라우저 악성 코드 실행:
    • 브라우저를 통해 악성 소프트웨어를 배포.

 

XSS의 종류

  • Stored XSS
    • 공격자가 취약점이 있는 Web Application에 악성 스크립트를 영구적으로 저장하여 다른 사용자에게 전달하는 방식
    ex) 게시판(HTML) 글 작성
<script>alert(document.cookie);</script>
  • 해당 script를 게시글에 삽입하면 HTML로 구성되어 있기 때문에 해당 스크립트가 조회하는 사용자에게 실행된다.
  • Reflected XSS
    • 공격 스크립트가 서버에 저장되지 않고 즉시 반사되어 실행됨.
    • URL에 포함된 파라미터나 입력값을 통해 전달.
    • 외부 링크 페이지로 이동시킨다.
    ex) 메일 내 첨부된 링크 클릭 → 가짜 사이트로 연결
  • DOM based XSS
    • 서버와 상관없이 클라이언트 측 JavaScript에서 발생.
    • DOM(Document Object Model)을 조작하여 악성 스크립트를 실행.
  • 해결방법
    1. 입/출력 값을 검증(Validation)하고 필터링하여 해결한다.
    2. 외부 보안관련 라이브러리를 사용한다.
    3. 보안 솔루션을 사용한다.

 

 

Persistence Framework

📌 애플리케이션에서 데이터를 영구적으로 저장하고 관리하기 위해 데이터베이스와 같은 저장소와의 상호 작용을 단순화하는 소프트웨어 도구이다.

 

Persistence Framework 개요 

  • JDBC의 한계
    1. 간단한 SQL을 실행하는 경우에도 중복된 코드가 너무 많았다.
public class PreparedStatementExample {
    public static void main(String[] args) {
        try {
						// ojdbc6.jar[oracle.jdbc.driver.OracleDriver] 파일을 라이브러리에 추가한다.
						Class.forName("oracle.jdbc.driver.OracleDriver");
						
						// 1. Connection
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase", "username", "password");
            String query = "SELECT * FROM employees WHERE department = ?";
            
            // 2. Statement
            PreparedStatement preparedStatement = connection.prepareStatement(query);
            
            // 값을 설정
            preparedStatement.setString(1, "HR");
            
            // 3. ResultSet
            ResultSet resultSet = preparedStatement.executeQuery();
            
            while (resultSet.next()) {
                // 결과 처리 코드
            }
            
            resultSet.close();
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  • onnection, Prepared Statement, ResultSet 등
  1. DB에 따라 일관성 없는 정보를 가진 채로 Checked Exception(SQL Exception) 처리를 한다.
    • Checked Exception인 SQLException은 개발자가 명시적으로 처리해야 한다.
    • 각 DBMS는 고유한 SQL 문법과 오류 코드 체계를 가지고 있다.
      • JDBC에서 발생하는 SQLException은 이러한 DBMS에 따라 달라질 수 있으며, 예외 메시지나 코드도 DB마다 다를 수 있다. 즉, 모두 그에 맞게 처리해야 한다.
  2. Connection과 같은 공유 자원을 제대로 반환하지 않으면 한정된 시스템 자원(CPU, Memory)에 의해 서버가 다운되는 등의 문제가 발생한다.
  3. SQL Query를 개발자가 직접 작성한다.
    • 중복 적인 쿼리 및 코드 작성이 필요하다.
    • 대부분의 테이블에 CRUD하는 쿼리가 포함된다.
  • Persistence Framework의 등장
    • JDBC 처럼 복잡함이나 번거로움 없이 간단한 작업만으로 Database와 연동되는 시스템
    • 모든 Persistence Framework는 내부적으로 JDBC API를 이용한다.
    • preparedStatement를 기본적으로 사용한다.
    → 위에서 JDBC를 설명한 이유.
    • 크게 SQL Mapper, ORM 두가지로 나눌 수 있다.
  • JDBC, SQL MAPPER, ORM의 공통점
    • 영속성(Persistence) 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성, 영구히 저장되는 특성

 

 

Persistence Framework의 역할

  1. 데이터 접근 로직 간소화:
    • JDBC와 같은 저수준 API의 반복 작업을 제거.
  2. 객체와 관계형 데이터 매핑:
    • 객체지향 언어(Java)의 데이터와 관계형 데이터베이스 간의 불일치를 해결.
  3. 트랜잭션 관리:
    • 데이터 작업을 트랜잭션 단위로 처리하여 데이터 무결성 보장.
  4. 데이터베이스 독립성:
    • 특정 데이터베이스에 종속되지 않고, 다양한 RDBMS와 연동 가능.
  5. 쿼리 생성 최적화:
    • 동적 쿼리 생성을 자동화하거나 간소화.

 

 

Persistence Framework의 특징

  • ORM (Object-Relational Mapping):
    • 객체 모델과 관계형 데이터베이스를 매핑.
    • 데이터베이스 작업을 객체지향 방식으로 처리.
  • SQL 추상화:
    • SQL 쿼리를 자동 생성하거나 간소화된 API로 대체.
  • 트랜잭션 지원:
    • ACID 특성을 보장하는 트랜잭션 처리.
  • 데이터베이스 연결 관리:
    • 커넥션 풀을 사용해 데이터베이스 연결 성능을 최적화.

 

주요 Persistence Framework

a. Hibernate

  • 설명: JPA(Java Persistence API)의 구현체 중 하나로 가장 널리 사용됨.
  • 특징:
    • 완전한 ORM 지원.
    • 동적 쿼리 및 캐시 지원.
    • 다양한 데이터베이스와 호환 가능.

b. JPA (Java Persistence API)

  • 설명: Java 표준 ORM API로, 데이터베이스와 객체 간 매핑을 정의.
  • 특징:
    • Hibernate, EclipseLink와 같은 구현체가 필요.
    • 표준화된 인터페이스 제공.

c. MyBatis

  • 설명: SQL 매핑 기반의 Persistence Framework.
  • 특징:
    • SQL을 직접 작성하여 세부적인 제어 가능.
    • 자동 매핑 기능 지원 (SQL 결과와 객체 매핑).

d. Spring Data JPA

  • 설명: JPA를 더 간단하게 사용할 수 있도록 지원하는 Spring 모듈.
  • 특징:
    • 기본 CRUD 작업을 간소화.
    • Repository 패턴 지원.

e. EclipseLink

  • 설명: JPA의 또 다른 구현체로, Oracle과 밀접한 통합.
  • 특징:
    • 성능 최적화와 고급 기능 지원.

 

ORM과 SQL 매핑 프레임워크 비교

  ORM (Hibernate, JPA) SQL 매핑 (MyBatis)
쿼리 작성 방식 자동 생성 (HQL, JPQL) 직접 작성 (SQL 문장 사용).
생산성 높은 추상화로 간단한 작업은 편리. 복잡한 쿼리 작성에 유리.
유연성 쿼리 최적화가 어려울 수 있음. 세부적인 제어 가능.
학습 곡선 ORM의 개념 이해 필요. SQL 지식만으로 쉽게 접근 가능.
사용 사례 CRUD 중심의 애플리케이션. 복잡한 데이터 조작 및 최적화된 쿼리 필요.

 

 

Persistence Framework의 장점

  1. 생산성 향상:
    • 데이터 접근 로직을 간소화.
  2. 데이터베이스 독립성:
    • 다양한 RDBMS와 호환 가능.
  3. 코드 간결화:
    • CRUD 작업의 반복 코드를 제거.
  4. 트랜잭션 관리:
    • ACID 특성을 쉽게 적용 가능.
  5. 객체-관계 매핑:
    • 객체지향적인 데이터 접근 가능.

 

Persistence Framework의 단점

  1. 복잡성 증가:
    • ORM 개념 학습과 설정이 필요.
  2. 쿼리 최적화 한계:
    • ORM에서는 복잡한 SQL 튜닝이 어려울 수 있음.
  3. 퍼포먼스 문제:
    • 자동 생성된 쿼리가 비효율적일 수 있음.
  4. 추상화의 비용:
    • 프레임워크의 내부 동작을 이해해야 문제를 해결 가능.

 

Persistence Framework 선택 가이드

요구사항 권장 프레임워크
간단한 CRUD 애플리케이션 Spring Data JPA, Hibernate
복잡한 SQL 쿼리 작업 MyBatis
높은 데이터베이스 독립성 필요 JPA
빠르고 세부적인 SQL 제어 필요 MyBatis
대규모 트랜잭션 관리 및 확장성 요구 Hibernate, JPA

 

 

 

SQL Mapper

📌 SQL 쿼리와 객체(Object) 간의 매핑을 지원하는 도구입니다. 직접 작성한 SQL 문의 실행 결과와 객체(Object)의 필드를 Mapping하여 데이터를 객체화한다. 대표적인 SQL Mapper로 Spring JDBC Template, MyBatis가 있다.

 

  • Spring JDBC Template
    • Spring Framework에서 제공하는 JDBC 작업을 단순화하고 개선한 유틸리티 클래스
  • JDBC Template의 장점
    1. 간편한 데이터베이스 연결
      1. 손수 적었던 Connection 관련 코드들을 yml 혹은 properties 파일에 설정만으로 해결한다.
    2. Prepared Statement를 사용한다.
    3. 예외 처리와 리소스 관리
      1. DB Connection을 자동으로 처리하여 리소스 누수를 방지한다.
    4. 결과 집합(ResultSet) 처리
      1. 데이터를 자바 객체로 변환할 수 있도록 돕는다.
    5. 배치 처리 작업을 지원한다.
      1. 매일 동일한 시간에 수행되는 쿼리, 주로 통계에 사용된다.
// 1. XML OR Gradle에 Spring JDBC 의존성 추가
// 2. application.properties OR application.yml에 데이터베이스 연결 설정

@RestController
public class MemberController {
    private final MemberRepository memberRepository;

    public MemberController(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @GetMapping("/members")
    public List<Member> findById(Long id) {
        return memberRepository.findById(id);
    }
}

// Member Object
public class Member {
    private Long id;
    private String name;
    private int age;

    // Getter and Setter methods
}

// Repository Anotation의 역할에 대해 공부해주세요.
@Repository
public class MemberRepository {
    private final JdbcTemplate jdbcTemplate;

    public MemberRepository(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

		// Member 객체로 리턴한다.
    public List<Member> findById(Long id) {
        String query = "SELECT * FROM MEMBER WHERE id = " + id;
        return jdbcTemplate.query(query, (rs, rowNum) -> {
            Member member = new Member ();
            member.setId(rs.getLong("id"));
            member.setName(rs.getString("name"));
            member.setAge(rs.getInt("age"));
            return member;
        });
    }
}

 

 

대표적인 SQL Mapper

  1. MyBatis:
    • SQL 기반의 가장 널리 사용되는 SQL Mapper.
    • 간단한 XML 매핑 설정으로 SQL과 객체를 연결.
  2. JDBC Template (Spring):
    • Spring에서 제공하는 SQL 처리 도구.
    • SQL Mapper와 비슷한 역할 수행.
  3. iBatis:
    • MyBatis의 이전 버전으로, MyBatis로 발전됨.

 

SQL Mapper의 한계

  1. SQL을 직접 다룬다.
  2. 특정 DB에 종속적으로 사용하기 쉽다.
    1. DB마다 Query문, 함수가 조금씩 다르다.
    → 다른 DB를 사용하면 쿼리도 변경해야할 가능성이 높다.
  3. 테이블마다 비슷한 CRUD SQL, DAO(Data Access Object) 개발이 반복된다. → 코드 중복
  4. 테이블 필드가 변경될 시 이와 관련된 모든 DAO의 SQL문, 객체의 필드 등을 수정해야 한다.
    1. 코드상으로 SQL과 JDBC API를 분리했지만 논리적으로 강한 의존성을 가지고 있다.
  5. 객체와의 관계는 사라지고 DB에 대한 처리에 집중하게 된다. → SQL 의존적인 개발
  • 관계형 DB와 객체지향의 패러다임 불일치
    • 객체지향으로 설계된것을 관계형 DB에 저장하기란 어렵다.
    • 테이블에 저장한 데이터를 다시 객체화 하는것도 어렵다.
// 1. 객체 안의 객체
public class Member {
	// 필드들..
	private Team team;
} -> ERD?

// 2. 상속 구조
public class Member extends Person {
	// 필드들..
} -> ERD?

// 3. extends, implements
public class Member extends Person implements Workable {
  // 필드들..
} -> ERD?

 

  • 객체지향 : 캡슐화, 추상화, 상속, 다형성 → 객체 중심
  • 관계형 데이터베이스(RDB) → 데이터 중심의 구조
  • 각각 지향하는 목적이 다르기 때문에 사용 방법과 표현 방식에 차이가 있다.

 

요약

  1. JDBC → SQL Mapper(JDBC Template, Mybatis) → ORM(JPA Hibernate)
  2. Persistence Framework는 모두 JDBC API를 내부적으로 사용하고 있다.
  3. SQL Mapper, ORM 들은 내부적으로 Prepared Statement를 사용하고있다.
  4. SQL Mapper, ORM 들은 Database Connection등 리소스 관리를 자동으로 해주고있다.
  5. Persistence Framework는 저장소와의 상호 작용을 단순화 한다.

 

 

MyBatis

📌 SQL 쿼리들을 XML 파일에 작성하여 코드와 SQL을 분리하여 관리되도록 만들어준다.

  • SQL과 Java Code의 분리가 핵심
  • Query를 JAVA에서 XML로
    • 복잡한 JDBC 코드가 사라진다.
    • ResultSet과 같이 결과값을 맵핑하는 객체가 없다.
    • 설정이 간단하다.
    • 관심사를 분리한다. → SQL 을 따로 관리한다.
    • XML 안에있는 SQL을 Java의 메소드에 매핑해준다.
  • MyBatis 장점
    1. 자동으로 Connection 관리를 해주면서 JDBC 사용할 때의 중복 작업 대부분을 없애준다.
    2. DB 결과 집합을 자바 객체로 매핑할 수 있다.
    3. 복잡한 쿼리나 다이나믹하게(동적쿼리) 변경되는 쿼리 작성이 쉽다.
      1. 상황에 따라 분기처리(IF)를 통해 쿼리를 동적으로 만들어주는것.
    4. 관심사 분리 - DAO로부터 SQL문을 분리하여 코드의 간결성 및 유지보수성이 향상된다.
    5. 쿼리 결과를 캐싱하여 성능을 향상시킬 수 있다.
// User 클래스
public class User {
    private Long id;
    private String userName;
    private String email;

    // Getter and Setter methods
}



// Mapper Interface 생성 : SQL 쿼리와 매핑을 정의하는 인터페이스
public interface UserMapper {
    User getUserById(Long id);
}


public class Main {
    public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        try (Reader reader = Resources.getResourceAsReader(resource)) {
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            try (SqlSession session = sqlSessionFactory.openSession()) {
                UserMapper userMapper = session.getMapper(UserMapper.class);
                User user = userMapper.getUserById(1L);
                System.out.println(user.getId() + ", " + user.getUsername() + ", " + user.getEmail);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

Mapper XML

SQL 쿼리와 객체 매핑을 정의한다.

<mapper namespace="com.example.UserMapper">
    <select id="getUserById" resultType="com.example.User">
        SELECT id, userName, email
        FROM users
        WHERE id = #{id}
    </select>
</mapper>

MyBatis 설정 파일 작성

<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
                <property name="userName" value="userName" />
                <property name="password" value="password" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/example/UserMapper.xml" />
    </mappers>
</configuration>