티스토리 뷰
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 김영한 인프런 강의 참고
JDBC APImysql 설치- 순수 JDBC API로 DB 접근하기
- DB 교체를 위한 스프링 설정 변경
순수 JDBC API로 DB 접근하기
MemberRepository
를 JDBC API로 다시 구현한다.
.../repository/JdbcMemberRepository.java
// ...
public class JdbcMemberRepository implements MemberRepository {
// database 연결 정보를 담고 있는 객체
private final DataSource dataSource;
public JdbcMemberRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Member save(Member member) {
// TODO Auto-generated method stub
return null;
}
@Override
public Optional<Member> findById(Long id) {
// TODO Auto-generated method stub
return Optional.empty();
}
@Override
public Optional<Member> findByName(String name) {
// TODO Auto-generated method stub
return Optional.empty();
}
@Override
public List<Member> findAll() {
// TODO Auto-generated method stub
return null;
}
}
우선 기본적인 구조는 위와 같다.
DataSource
는 데이터베이스 커넥션을 획득할 때 사용하는 객체다. 스프링 부트는 데이터베이스 커넥션 정보를 바탕으로 DataSource
를 생성하고 스프링 빈으로 만들어둔다. 그래서 DI를 받을 수 있다.
각 메서드의 구현은 코드가 상당히 길어지고 반복이 많기 때문에 대표적으로 save 메서드의 코드만 분석해 보겠다. (전체 코드는 github참고 : https://github.com/on1ystar/springForPractice/blob/master/practice/src/main/java/com/example/practice/repository/JdbcMemberRepository.java)
// ...
@Override
public Member save(Member member) {
String sql = "insert into member(name) values(?)";
// DB의 연결 정보를 가지고 일정 시간 동안 DB와 연결할 수 있도록 통로 역할을 하는 객체
Connection conn = null;
// 다양한 SQL 구문들을 정의하고 바인딩 하는 방법들과 실제 DB로 전송하는 방법들이 정의된 객체
PreparedStatement pstmt = null;
// sql 쿼리 결과를 저장하는 데이터 집합 객체
ResultSet rs = null;
try {
conn = getConnction();
pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
// sql string의 첫 번째 '?'에 member의 name 값을 바인딩
pstmt.setString(1, member.getName());
// DB에 바인딩 된 sql 전송
pstmt.executeUpdate();
// 쿼리 결과 데이터 집합 반환
rs = pstmt.getGeneratedKeys();
// 반환된 데이터 결과에 따른 예외처리
if (rs.next()) {
member.setId(rs.getLong(1));
} else {
throw new SQLException("id 조회 실패");
}
return member;
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
// ...
// 할당한 리소스 해제
private void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
close(conn);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
// Connection 객체 리소스 해제
private void close(Connection conn) throws SQLException {
DataSourceUtils.releaseConnection(conn, dataSource);
}
JDBC api는 예외를 많이 던지므로 전체적으로 try ~ catch
문을 사용한다.
java.sql
Java 프로그래밍 언어를 사용하여 데이터 소스(일반적으로 관계형 데이터베이스)에 저장된 데이터에 액세스하고 처리하기 위한 API를 제공
주요 클래스 및 인터페이스
Connection
:Statement
를 만들고, 연결 및 속성을 관리하는 방법을 제공Statement
: 기본 SQL 문을 보내는 데 사용됨PreparedStatement
: 미리 생성된Statement
또는 기본 SQL 문을 전송하는 데 사용됨 (derived fromStatement
)ResultSet
: 데이터베이스 결과 집합을 나타내는 데이터 테이블
conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)
미리 컴파일 된 SQL 문을 나타내는 객체를 반환
- sql : 쿼리를 날릴 sql문을
String
타입으로 생성해 넘겨줌. 이때?
를 사용하면 추후 동적으로 값을 넣어 바인딩할 수 있음 Statement.RETURN_GENERATED_KEYS
: 자동으로 생성되는sequence
키를 추후에 반환받을 수 있음
pstmt.executeUpdate()
PreparedStatement
객체에서 SQL 문을 실행.
INSERT
, UPDATE
또는 DELETE
와 같은 SQL Data Manipulation Language(DML) 문이거나 DDL 문과 같이 아무것도 반환하지 않는 SQL 문
참고로 SELECT
는 executeQuery()
이고 반환 타입은 ResultSet
next()
ResultSet
객체는 반환된 결과를 테이블 형식으로 저장하고 있으며, 현재 행을 가리키는 cursor값을 가지고 있음
커서를 현재 위치에서 한 행 앞으로 이동시키며, 다음 행이 있으면 true
, 현재 행이 마지막 행이라 다음 행이 없으면 false
를 반환
리소스 해제
할당한 순서의 반대로 해제
rs.close()
pstmt.close()
DataSourceUtils.releaseConnection(conn, dataSource)
DB 교체를 위한 스프링 설정 변경
우리는 이전에 DB가 교체될 것을 가정하고 MemberRepository
를 인터페이스로 설계했다. 이를 구현한 구현체가 MemoryMemberRepository
였으며, 이제 JdbcMemberRepository
가 추가되었다.
이제 아래와 같이 스프링 설정 파일 SpringConfig.java
에서 memberRepository
가 JdbcMemberRepository
를 반환하도록 코드를 바꿔주면 간단하게 DB를 메모리에서 mysql로 변경할 수 있다.
.../SpringConfig.java
@Configuration
public class SpringConfig {
private final DataSource dataSource;
public SpringConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
MemberRepository memberRepository() {
// return new MemoryMemberRepository();
return new JdbcMemberRepository(dataSource);
}
}
위와 같이 DataSource
객체를 선언해 준 뒤, JdbcMemberRepository
객체를 생성하는 생성자 매개변수 값으로 넣어준다.
그러면 스프링이 memberRepository
빈 생성 시, DataSource
객체를 알아서 DI로 주입한다.
위와 같은 설계 방식을 개방-폐쇄 원칙(OCP, Open-Closed Principle)이라고 한다. 이는 확장에는 열려있고, 수정, 변경에는 닫혀있다는 특징이 있다.
(참고 :2023.02.07 - [프로그래밍 언어 공부/Java] - [Java] 객체 지향 설계 5원칙 - SOLID)
더불어 스프링의 DI (Dependencies Injection)을 사용하면 기존 코드를 전혀 손대지 않고, 설정만으로 구현 클래스를 변경할 수 있다.
Reference
'Spring&Spring Boot' 카테고리의 다른 글
[Spring Boot] 입문 - JPA를 사용하는 이유 (0) | 2023.02.23 |
---|---|
[Spring Boot] 입문 - JDBC Template(feat. 스프링 통합 테스트) (0) | 2023.02.21 |
[Spring Boot] 입문 - 순수 JDBC로 DB 연결하기(feat. mysql) - 1 (0) | 2023.02.17 |
[Spring Boot] 입문 - 회원 관리 예제(웹 MVC 개발) (0) | 2023.02.11 |
[Spring Boot] 입문 - 스프링 빈과 컨테이너, 그리고 의존 관계(feat. IoC, DI) (0) | 2023.01.01 |
- Total
- Today
- Yesterday
- Python Cookbook
- JPA
- 방명록 프로젝트
- Thymeleaf
- 생활코딩 javascript
- Spring
- Do it! 정직하게 코딩하며 배우는 딥러닝 입문
- 프로그래머스
- 스프링 컨테이너
- 패킷 스위칭
- 지옥에서 온 git
- spring mvc
- git
- 스프링 테스트
- 파이썬 for Beginner 솔루션
- Computer_Networking_A_Top-Down_Approach
- 쉽게 배우는 운영체제
- git branch
- 운영체제 반효경
- git merge
- 선형 회귀
- 파이썬 for Beginner 연습문제
- 쉘 코드
- jsp
- 스프링 mvc
- Spring Data JPA
- 스프링
- Spring Boot
- 김영환
- Gradle
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |