스프링부트가 지원하는 인메모리 관계형 데이터베이스인 H2 db 연결하기
h2의 장점으로는 따로 설치가 필요없는 아주 가벼운 웹용 로컬 DB이다!
(설치 가이드는 쉽고 쉽게 설명된 다른 글들이 많으니 패스~)
H2 연결 성공!

insert into member(name) values("spring")라고 ""쓰면 에러.. 꼭 작은따옴표..
오라클할 때 배웠는데도 실수하는 저란 사람 ㅠㅠㅠ
자바는 db연동을 하려면 jdbc가 꼭 있어야 한다.

의존성 추가한다음에 꼭 우측 상단 코끼리 눌러서 업로드 해주기!
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
application.properties에서도 연결해주기
datasourrce url 은(h2데이터베이스 깔때 설정했던 url)
package com.example.spring.repository;
import com.example.spring.domain.Member;
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.springframework.jdbc.datasource.DataSourceUtils.getConnection;
public class JdbcMemberRepository implements MemberRepository{
private final DataSource dataSource;
public JdbcMemberRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Member save(Member member) {
String sql = "insert into member(name) values(?)";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
conn = getConnection();
pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
pstmt.setString(1, member.getName());
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
if(rs.next()){
member.setId(rs.getLong(1));
}else{
throw new SQLException("id 조회 실패");
}
return member;
}catch (SQLException e) {
throw new IllegalStateException(e);
}finally {
close(conn, pstmt, rs);
}
}
@Override
public Optional<Member> findById(Long id) {
String sql = "select * from member where id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, id);
rs = pstmt.executeQuery();
if(rs.next()){
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return Optional.of(member);
}else{
return Optional.empty();
}
} catch (SQLException e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
@Override
public Optional<Member> findByName(String name) {String sql = "select * from member where name = ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "name");
rs = pstmt.executeQuery();
if(rs.next()){
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return Optional.of(member);
}else{
return Optional.empty();
}
} catch (SQLException e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
@Override
public List<Member> findAll() {
String sql = "select * from member";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
List<Member> members = new ArrayList<>();
while (rs.next()){
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
members.add(member);
} return members;
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
private Connection getConnection() {
return DataSourceUtils.getConnection(dataSource);
}
private void close(Connection conn, PreparedStatement pstmt, ResultSet rs){
try {
if(rs != null) rs.close();
if(conn != null) conn.close();
if(pstmt != null) pstmt.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
순수 JDBC로 작업한 어마어마한 코드량.. 예전에는 모두 이렇게 했다고..
근데 저도 학원에서 이렇게 배웠습니다만..ㅎ
*참고로 데이터베이스는 외부와 소통하는거긴 때문에 자원을 쓰고 난후에는 꼭 끊는 close()작업을 해야한다.!!
(안하다 쌓이면 나중에 대장애가 올수도 있다...)
package com.example.spring;
import com.example.spring.repository.JdbcMemberRepository;
import com.example.spring.repository.MemberRepository;
import com.example.spring.repository.MemoryMemberRepository;
import com.example.spring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class SpringConfig {
private DataSource dataSource;
@Autowired
public SpringConfig(DataSource dataSource){
this.dataSource = dataSource;
}
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
//return new MemoryMemberRepository(); 원래 메모리에 저장해놨던걸 구현체만 바꿔 설정해 데이터베이스에 저장한다.
return new JdbcMemberRepository(dataSource);
}
}
자바의 큰 장점인 다형성의 활용!
인터페이스를 두고 구현체는 내 마음대로 바꿀수 있게 해준다.
기능을 완전히 변경하더라도 전체 수정을 하지 않는다.
조립하는 코드는 수정하더라도 실제 애플리케이션이 동작하는 코드는 수정이 필요없다!
SOLID
개방-폐쇄 원칙(OCP; Open-Closed Principle)
확장에는 열려있고, 수정(변경)에는 닫혀있다.
스프링의 DI(Dependencies Injention)을 사용하면 기존 코드를 전혀 손대지 않고, 설정만으로 구현 클래스를 변경할 수 있다.
'Spring' 카테고리의 다른 글
JdbcTemplate (0) | 2023.11.01 |
---|---|
스프링 빈과 의존 관계 설정 (0) | 2023.10.25 |
스프링 부트를 이용하여 웹을 개발하는 3가지 방법 (0) | 2023.10.22 |
강의 들으며 스프링 다시 시작! (0) | 2023.10.21 |