해당 내용의 출처는 김영한 님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술의 강의 내용이고,본 포스트는 수강후 개인적으로 공부한 내용을 필기하고 다시 복습하기 위하여 작성되었고, 기타 내용을 보충하기 위한 부분은 관련링크로서 출처를 밝힌다.
출처
관련 링크1 :: https://velog.io/@ddusi/Spring-1
Spring에 MySQL 연동하기
Spring boots를 하면서 기존에 수업때는 H2라는 데이터베이스를 사용하였다. 하지만, 이번에는 MySQL을 연동하기 위해서 MySQL driver를 설치하여 사용하려고 했는데, 자동적으로 연결이 안되서 매우 고
velog.io
관련 링크2 :: https://sas-study.tistory.com/160
관련 링크3 :: https://victorydntmd.tistory.com/321
관련 링크4 :: https://pyxispub.uzuki.live/?p=1715
관련 링크5 :: https://jogeum.net/6
1. 서론
본 학습내용 정리의 장에서는 Spring 내부의 JDBC와 관련한 내용을 정리하였다. JDBC가 무엇인지에 대한 내용은 Java/JSP에서 다룬 내용을 확인하면 되겠다.
2. 순수 JDBC를 이용한 JDBC Driver를 구현하여 DB에 접근
스프링 프레임워크에서는 JDBC JPA를 제공하고 있다. 따라서, 이전 Servlet과 JSP만을 이용한, 혹은 그 이전의 방식대로 JDBC를 구현하여 사용할 필요가 없어진 것이다.
그러나 JDBC를 제대로 사용하기 위하여, 원리를 알고 있어야 하는 것이 보다 나을 수 있기 때문에, Spring에서 제공하는 JPA를 사용하지 않고 순수 JDBC만을 이용하여 원리를 파악해보고 그 내용을 정리하여 보았다.
다음은 내용을 진행하기 이전 실습의 환경에 대한 가정이다.
- 1. 스프링부트를 이용하였다.
- 2. MySQL(MariaDB)를 이용하였다.
- 3. Intelli J를 사용하여 실습을 진행하였다.
- 4. 사용된 빌드툴은 Gradle이다.
첫째로, 스프링에서 JDBC를 구현하기 위해서는 사용하고자 하는 DB와 관련한 의존성을 주입해주어야 한다. 만일, 프로젝트 생성시 해당 의존성을 주입한 상태로 프로젝트를 생성하였다면, 진행하지 않고 넘어가도 되는 부분이다. 내용은 예제와 같다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter'
runtimeOnly 'mysql:mysql-connector-java'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
DB관련 의존성 주입을 완료하였다면, 어플리케이션에게 데이터베이스와 관련된 정보를 알려주어 데이터베이스에 정상적으로 접속할 수 있도록 환경을 마련해주어야 한다. application.properties에 관련 예제의 내용을 입력하여 데이터베이스와 관련된 속성을 입력한다.
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/example?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username="DB아이디"
spring.datasource.password="DB비밀번호"
/*
datasource.url과 관련된 추가정보
?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul&useOldAliasMetadataBehavior=true&zeroDateTimeNehavior=convertToNull&connectTimeout=60
*/
예제에서 각각의 정보는 다음과 같다.
- 1. datasource.driver-class-name : 사용하고자 하는 jdbc driver 클래스명
- 2. datasource.url : DB와의 연결정보를 나타낸다 각각의 내용은 다음과 같음, 더 많은 정보는 예제의 하단에 추가정보를 확인해보면 된다.
- jdbc:mysql://"DB 호스트":"포트번호"/"DB이름"
- ?serverTimezone=UTC : URL 쿼리 스트링에 serverTimezone을 작성함
- characterEncoding=UTF-8 : UTF-8로 인코딩함
- 3. datasource.username : DB아이디 를 입력한다.
- 4. datasource.password : DB 비밀번호 를 입력한다.
참고) DB 아이디 및 비밀번호를 입력할때 "" 혹은 ''은 필요없이, 그대로 입력하면 작동한다.
예제는 데이터베이스와의 커넥션 관련 정보이다. 예제를 참고하여 커넥션 정보를 작성한 뒤, 프로젝트 내부의 application.properties에 추가하여 속성을 부여해주어야만 DB와 정상적으로 연결이 된다.
예제를 통하여 DB와의 연결을 마쳤으면, 다음으로는 DB에 전송할 sql을 작성하여야 한다. prestatement로서 작성하는 방법은 다음의 예제와 같고, 만일 왜 prestatement를 작성해야 하는지 모른다면, 이전 php의 sqlInjection 공격에 관한 내용을 참고하자.
// DB에 전송할 쿼리문을 작성한다. preStatement
String sql = "INSERT INTO `member` SET `name` = ?";
// DB와의 연결과 관련된 정보를 담을 변수들을 선언
Connection conn = null;
PreparedStatement pstmt = null;
// DB통신과의 결과를 담을 변수
ResultSet rs = null;
// DB연결과 관련된 핵심 로직
try {
// DB와의 커넥션을 불러와 할당한다.
conn = getConnection();
// 우선 작성된 sql을 저장하고, prestatement의 RETURN_GENERATED_KEYS라는 옵션을 사용한다.
// RETURN_GENERATED_KEYS는 DB에 Insert한 후, 리턴받을 번호를 가져오는 옵션이다.
pstmt = conn.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS);
// 첫번째 ?와 member의 name을 매핑하여 치환한다.
pstmt.setString(1, member.getName());
// DB에 실제 쿼리가 발송된다.
pstmt.executeUpdate();
// RETURN_GENERATED_KEYS 로 얻은 값을 불러와서 rs에 저장한다.
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 {
// DB와의 통신이 종료되면 반드시 연결을 종료해주어야 한다.
close(conn, pstmt, rs);
}
DB와의 통신을 통한 정보를 불러오는 예제는 상기의 예제 그리고 그 주석과 같다. 여기서 연결을 종료하는 메소드를 다시 한 번 살펴보면 하기와 같다.
// DB와의 연결을 종료하는 메소드
private void close(Connection conn, PreparedStatement pstmt, ResultSet rs)
{
// 역순으로 DB와의 연결을 종료한다.
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();
}
}
작성된 예제외에도 더 나은 방법들이 존재한다. 그러나 실제로 현재 이 로직들은 잘 사용되지 않기 때문에 고전스타일로 작성된 예제이며, 에제는 DB에 데이터를 추가하는 기능을 주제로 작성된 것임으로, 만일 데이터 조회, 삭제, 수정 등 다른 로직이 필요할 때는 쿼리문과 옵션 등을 수정하여 작성할 수 있다.
참조 1)
커넥션을 획득하려 할 때,
public JdbcMemberRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
에서 dataSource.getConnection() 과 같이 직접 획득할 수 도 있으나, 트랜젝션등의 문제가 발생할 수 있으니
private Connection getConnection() {
return DataSourceUtils.getConnection(dataSource);
}
상기와 같이 획득하면 커넥션이 유지됨으로 트랜젝션의 문제에서 보다 안전할 수 있다. 트랜잭션은, MySQL 란에 정리해 둔 내용이 있으니, 혹시 이해에 어려움이 있다면 참고하자.
3. 결론
이로서 순수 JDBC를 이용한 JDBC 드라이버를 구현한 DB접근에 대한 내용 정리를 마치도록 한다. 본 내용은 대단원인 Spring에서의 JDBC를 이해하기 위한 제일 첫번째 단계로서, Spring 출시 이전에 개발자들이 어떻게 JDBC를 구현하였고, 어떤 어려움이 있었기 때문에 Spring의 JDBC는 그러한 형태를 가지게 되었나를 알기 위하여 작성되었다.
다음장에서는 Spring의 JDBC Template를 이용하여 DB를 접근하는 방법에 대한 내용을 정리하도록 하겠다.
'Framework > Spring' 카테고리의 다른 글
Spring 오류 정리 1. Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. (0) | 2021.08.05 |
---|---|
Spring 공부내용 정리 : 3. Spring 에서의 JDBC #3 (0) | 2021.08.04 |
Spring 공부내용 정리 : 3. Spring 에서의 JDBC #2 (0) | 2021.08.01 |
Spring 공부내용 정리 : 2. Bean과 의존관계 (0) | 2021.07.29 |
Spring 공부내용 정리 : 1. 테스트 코드 (0) | 2021.07.25 |