[스프링 인 액션] 3장 JDBC : 데이터로 작업하기

    3장 데이터로 작업하기 - JDBC

    💻 실습 : https://github.com/cusbert/spring-in-action-5th

    🎯 이 장에서 배우는 내용

    • 스프링 JdbcTemplate 사용하기
    • SimpleJdbcInsert 사용해서 데이터 추가하기

    3.1 JDBC를 사용해서 데이터 읽고 쓰기

    • 관계형 데이터를 사용할 때 선택지는 JDBC, JPA 두 개다
    • 스프링의 JDBC 지원은 JdbcTemplate 템플릿에 기반을 둔다
    • JdbcTemplate 를 사용해서 데이터베이스 쿼리하기
    • 명령문이나 데이터베이스 연결 객체를 생성하는 코드가 없다.
      메서드의 실행이 끝난 후 그런 객체들을 클린업하는 코드 또한 없다.
      catch 블록에서 올바르게 처리할 수 없는 예외를 처리하는 코드도 없다.
    @Override
    public Ingredient findById(String id) {
        return jdbcTemplate.queryForObject(
                "select id, name, type from Ingredient where id=?",
                this::mapRowToIngredient, id);
    }
    
    private Ingredient mapRowToIngredient(ResultSet rs, int rowNum) 
                throws SQLException {
        return new Ingredient(
                rs.getString("id"),
                rs.getString("name"),
                Ingredient.Type.valueOf(rs.getString("Type")));
    }

    3.1.2 JdbcTemplate 사용하기

    JDBC 환경 구성

    • pom.xml 에 JDBC 스타터 의존성 추가
        <!-- jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    • pom.xml 에 데이터베이스 의존성 추가 : mariadb
        <!-- mariadb -->
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
        </dependency>

    JDBC Repository 정의하기

    • @Repository 지정하면 Spring component 검색에서 이 클래스를 자동으로 컨텍스트의 빈으로 생성한다
    • JdbcIngredientRepository 빈이 생성되면 @Autowired를 통해 스프링이 해당 빈을 JdbcTemplate 에 주입한다
    • JdbcIngredientRepository의 생성자에서는 jdbcTemplate 참조를 인스턴수 변수에 저장한다
    • 이 변수는 데이터베이스의 데이터를 쿼리하고 추가하기 위해 다른 메서드에서 사용된다
    • findAll() : jdbcTemplate.query(sql, RowMapper 인터페이스) 사용
    • findById(String id) : jdbcTemplate.queryForObject(sql, RowMapper 인터페이스)
    • save(Object object): jdbcTemplate.update(sql, 쿼리 매게변수에 저장할 값만 인자로 전달)
    • Ingredient repository가 해야 할 일을 IngredientRepository 인터페이스에 정의
    public interface IngredientRepository {
        Iterable<Ingredient> findAll();
        Ingredient findById(String id);
        Ingredient save(Ingredient ingredient);
    }
    • JdbcTemplate 사용하여 IngredientRepository 구현
    @Repository
    public class JdbcIngredientRepository implements IngredientRepository {
    
        private JdbcTemplate jdbcTemplate;
    
        @Autowired
        public JdbcIngredientRepository(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    
        @Override
        public Iterable<Ingredient> findAll() {
            return jdbcTemplate.query(
                    "select id, name, type from Ingredient",
                    this::mapRowToIngredient);
    
        }
    
        @Override
        public Ingredient findById(String id) {
            return jdbcTemplate.queryForObject(
                    "select id, name, type from Ingredient where id=?",
                    this::mapRowToIngredient, id);
        }
    
        @Override
        public Ingredient save(Ingredient ingredient) {
            jdbcTemplate.update(
                    "insert into Ingredient (id, name, type) values (?, ?, ?)",
                    ingredient.getId(),
                    ingredient.getName(),
                    ingredient.getType().toString());
            return ingredient;
        }
    }

    3.1.3 스키마 정의하고 데이터 추가하기

    3.1.4 타코와 주문 데이터 추가하기

    • JdbcTemplate 으로 데이터 저장하는 방법

    JdbcTemplate 사용해서 데이터 저장하기

    • 깃허브 코드 참고
    • update()메소드는 PreparedStatementCreator 객체와 KeyHolder 객체를 인자로 받는다.
    • keyHolder.getKey().longValue()는 타코 ID 를 반환한다

    SimpleJdbcInsert 사용해서 데이터 저장하기

    @SessionAttributes

    • 세션에 모델객체를 저장해두고 계속 보존 가능하다
    • 사용이 끝나면 즉 db 저장이 완료되면 세션을 제거한다
    sessionStatus.setComplete();

    📌 요약

    • 스프링의 JdbcTemplate은 JDBC 작업을 굉장히 쉽게 해준다
    • 데이터데이스가 생성해주는 ID 값을 알아야 할 때는 PreparedStatementCreator 의 KeyHolder 사용한다
    • 데이터 추가를 쉽게 실행할 때는 SimpleJdbcInsert 사용한다

    참고

    반응형

    댓글

    Designed by JB FACTORY