서버

Spring boot3 - Spring JDBC에 대한 이해와 기본 실습

탐훈 2024. 11. 29. 12:28
728x90

기본 JDBC를 사용하려면

Connection부터 Query 날리고, ResultSet까지 가져오는 과정이 있다.

해당 과정은 JSP/Servlet으로 톰캣서버로 웹앱 제작시 사용했었는데

Spring이 들어오고 나서

작성 부분을 조금 더 쉽게 만들 수 있도록

 

"JdbcTemplate"이란 녀석을 만들었다.

 

이번 포스팅에서는 

JPA를 사용하기 전에 

Spring이 제공해주는 JDBC 객체로 

DB에 접근해 INSERT, DELETE를 해본다.


 

1. application.properties 설정

 

[application.properties]

spring.h2.console.enabled=true

spring.datasource.url=jdbc:h2:mem:testdb

 

 

 

2. resources/schema.sql 생성

 

[resources/schema.sql]

create table course
(
    id bigint not null,
    name varchar(255) not null,
    author varchar(255) not null,
    primary key (id)
);

insert into course (id, name, author) values (2, 'learn aws', 'in28minutes');

select * from course;

delete from course where id = 1;

 

 

 

3. Repository 생성

 

DB에 접근하는 객체는

Repository이다. 

 

[CourseJdbcRepository.java]

package com.in28minutes_springboot.lear_jpa_andhibernate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class CourseJdbcRepository {

    @Autowired
    private JdbcTemplate springJdbcTemplate;

    private static String INSERT_QUERY = 
            """
                insert into course (id, name, author) 
                values (?, ?, ?);
            """;

    private static String DELETE_QUERY = 
            """
                DELETE FROM COURSE 
                WHERE ID = ?
            """;

    public void insert(Course course) {
        springJdbcTemplate.update(INSERT_QUERY, course.getId(), course.getName(), course.getAuthor());
    }

    public void deleteById(long id) {
        springJdbcTemplate.update(DELETE_QUERY, id);
    }
}

 

 

 

Autowired로 선언한

JdbcTemplate을 보면

springframework 패키지에서 가져왔다

 

따라서 context 내에 어딘가 존재하기 때문에

@Autowired 해주면 자동 삽입(DI) 된다.

 

4. 테스트 코드 생성

 

[CourseJdbcCommandLineRunner.java]

package com.in28minutes_springboot.lear_jpa_andhibernate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class CourseJdbcCommandLineRunner implements CommandLineRunner{

    @Autowired
    private CourseJdbcRepository courseJdbcRepository;

    @Override
    public void run(String... args) throws Exception {
        Course course = new Course(3, "hello", "new Course!");
        courseJdbcRepository.insert(course);
        courseJdbcRepository.delete(3);
    }
    
}

 

 

CommandLineRunner 는 

코드를 바로 실행시켜주는 인터페이스고 

해당 인터페이스를 구현한 클래스를 생성한다. 

 

@Component를 선언한 이유는

@SpringBootApplication 어노테이션은

ScanComponent 어노테이션이 함께 들어있다.

 

ScanComponent 어노테이션은
하위에 있는 컴포넌트들을 검색해
Context로 실어준다

 

5. 엔티티 생성

 

[Course.java]

package com.in28minutes_springboot.lear_jpa_andhibernate;

public class Course {
    private long id;
    private String name;
    private String author;

    public Course() {

    }

    public Course(long id, String name, String author) {
        this.id = id;
        this.name = name;
        this.author = author;
    }

    public long getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public String getAuthor() {
        return this.author;
    }
}

 

 

 


6. Select를 해보자 

 

Spring JDBC가 아닌

JDBC로 조회하면 

ResultSet으로 리턴을 받는다.

 

한 줄씩 looping 해가며

데이터를 가져왔었는데

 

Spring JDBC에서는

Object를 던져주면

Row에 해당하는 Column들을 Mapping 해준다고 해서

-> RowMapper 객체를 제공해준다. 

 

위에서 작성한 두 파일을 수정하자


 

 

[CourseJdbcRepository.java]

package com.in28minutes_springboot.lear_jpa_andhibernate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class CourseJdbcRepository {

    @Autowired
    private JdbcTemplate springJdbcTemplate;

    private static String INSERT_QUERY = 
            """
                insert into course (id, name, author) 
                values (?, ?, ?);
            """;

    private static String DELETE_QUERY = 
            """
                DELETE FROM COURSE 
                WHERE ID = ?
            """;
    private static String SELECT_QUERY = 
            """
                SELECT FROM COURSE 
                WHERE ID = ?
            """;

    public void insert(Course course) {
        springJdbcTemplate.update(INSERT_QUERY, course.getId(), course.getName(), course.getAuthor());
    }

    public void deleteById(long id) {
        springJdbcTemplate.update(DELETE_QUERY, id);
    }

    public Course selectById(long id) {
        return 
            springJdbcTemplate.queryForObject(
                SELECT_QUERY, 
                new BeanPropertyRowMapper<>(Course.class),
                id
            );
    }
}

 

[CourseJdbcCommandLineRunner.java]

package com.in28minutes_springboot.lear_jpa_andhibernate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class CourseJdbcCommandLineRunner implements CommandLineRunner{

    @Autowired
    private CourseJdbcRepository courseJdbcRepository;

    @Override
    public void run(String... args) throws Exception {
        Course course = new Course(3, "hello", "new Course!");
        Course course2 = new Course(5, "hello", "new Course!");
        courseJdbcRepository.insert(course);
        courseJdbcRepository.insert(course2);
        courseJdbcRepository.deleteById(3);

        Course result = courseJdbcRepository.selectById(5);
        System.out.println("result > " + result);
        System.out.println("getId > " + result.getId());
        System.out.println("getAuthor > " + result.getAuthor());
    }
    
}