LUMI_dev
JDBC란? 본문
등장배경
더보기



서버는 데이터베이스와 어떠한 방법을 통해 소통을 할까?
애플리케이션 서버에서 DB에 접근하기 위해 여러가지 작업이 필요함

- 우선 DB에 연결하기 위해 커넥션 연결
- SQL을 작성한 후 커넥션을 통해 SQL을 요청
- 요청한 SQL에 대한 결과를 응답 받음
그러나 이 경우 기존에 사용하던 MySQL 서버를 PostgreSQL 서버로 변경해야 하는 상황에서
커넥션을 연결하는 방법, SQL을 전달하는 방법, 결과를 응답받는 방법 모두 달라질 수 있음

그래서 등장한 것이 JDBC 표준 인터페이스

JDBC (Java Database Connectivity) - DB 교체 간편하게
: DB에 접근할 수 있도록 Java에서 제공하는 API
JDBC Template - DB 연결 간편하게 (사용할 일은 희박)
커넥션 연결, statement 준비 및 실행, 커넥션 종료 등의 반복적이고 중복되는 작업들을 대신 처리
JDBC Template 사용방법
1 application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/memo
spring.datasource.username=root
spring.datasource.password={비밀번호}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2. build.gradle : JDBC 라이브러리, MySQL 추가
// MySQL
implementation 'mysql:mysql-connector-java:8.0.28'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
3. DB연결이 필요한 곳에서 JdbcTemplate을 주입 받아서 사용
private final JdbcTemplate jdbctemplate;
public MemoRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
생성자의 파라메터를 통해 JdbcTemplate 객체가 자동으로 넘어와 jdbctemplate 변수에 저장됨
실습)
MemoController
package com.sparta.sparta_memo_project.Controller;
import com.sparta.sparta_memo_project.dto.MemoRequestDto;
import com.sparta.sparta_memo_project.dto.MemoResponseDto;
import com.sparta.sparta_memo_project.entity.Memo;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.web.bind.annotation.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
@RestController
@RequestMapping("/api")
public class MemoController {
private final JdbcTemplate jdbcTemplate;
public MemoController(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@PostMapping("/memos")
public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
// RequestDto를 Entity로 만들기 - Entity (테이블의 한 행에 해당되는 데이터)
Memo memo = new Memo(requestDto);
// DB 저장
KeyHolder keyHolder = new GeneratedKeyHolder(); // 기본 키를 반환받기 위한 객체
String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)";
//여기에서의 update는 insert,delete,update를 처리하는 JdbcTemplate update 메소드
jdbcTemplate.update( con -> {
PreparedStatement preparedStatement = con.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS);
//첫번째 물음표
preparedStatement.setString(1, memo.getUsername());
//두번째 물음표
preparedStatement.setString(2, memo.getContents());
return preparedStatement;
},
keyHolder);
// DB Insert 후 받아온 기본키 확인
Long id = keyHolder.getKey().longValue();
memo.setId(id);
// Entity -> ResponseDto
MemoResponseDto memoResponseDto = new MemoResponseDto(memo);
return memoResponseDto;
}
@GetMapping("/memos")
public List<MemoResponseDto> getMemos() { //MemoDto가 하나 생성되면서 List 타입으로 묶여서 반환
// DB 조회
String sql = "SELECT * FROM memo";
return jdbcTemplate.query(sql, new RowMapper<MemoResponseDto>() {
@Override
public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
// SQL 의 결과로 받아온 Memo 데이터들을 MemoResponseDto 타입으로 변환해줄 메서드
//get~ 부분은 각 column의 데이터 타입
Long id = rs.getLong("id");
String username = rs.getString("username");
String contents = rs.getString("contents");
//위 코드로 MemoResponseDto가 하나 만들어짐
return new MemoResponseDto(id, username, contents);
}
});
}
@PutMapping("/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
// 해당 메모가 DB에 존재하는지 확인
Memo memo = findById(id);
if(memo != null) {
// memo 내용 수정
String sql = "UPDATE memo SET username = ?, contents = ? WHERE id = ?";
jdbcTemplate.update(sql, requestDto.getUsername(), requestDto.getContents(), id);
return id;
} else {
throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
}
}
@DeleteMapping("/memos/{id}")
public Long deleteMemo(@PathVariable Long id) {
// 해당 메모가 DB에 존재하는지 확인
Memo memo = findById(id);
if(memo != null) {
// memo 삭제
String sql = "DELETE FROM memo WHERE id = ?";
jdbcTemplate.update(sql, id);
return id;
} else {
throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
}
}
private Memo findById(Long id) {
// DB 조회
String sql = "SELECT * FROM memo WHERE id = ?";
return jdbcTemplate.query(sql, resultSet -> {
if(resultSet.next()) {
Memo memo = new Memo();
memo.setUsername(resultSet.getString("username"));
memo.setContents(resultSet.getString("contents"));
return memo;
} else {
return null;
}
}, id);
}
}
MemoResponseDto
package com.sparta.sparta_memo_project.dto;
import lombok.Getter;
import com.sparta.sparta_memo_project.entity.Memo;
@Getter
public class MemoResponseDto {
private Long id;
private String username;
private String contents;
public MemoResponseDto(Memo memo) {
this.id = memo.getId();
this.username = memo.getUsername();
this.contents = memo.getContents();
}
public MemoResponseDto(Long id, String username, String contents) {
this.id = id;
this.username = username;
this.contents = contents;
}
}
★ ★ ★
column 하나 = java 객체의 field 하나
테이블의 한 row = java 객체 하나