본문 바로가기
공부방

[TIL 06/29] NamedParameterJdbcTemplate, Transaction

by hseong 2023. 6. 30.

1. NamedParameterJdbcTemplate

JdbcTemplate은 인덱스 기반의 파라미터 바인딩을 통해서 다음과 같이 작성될 수 있다.

@Override
public void update(Customer customer) {
    String sql = "update customers set name = ? where customer_id = ?";
    jdbcTemplate.update(sql,
            customer.getName(),
            customer.getCustomerId().toString());
    }

?를 입력한 자리에 메서드에 전달한 인수가 순서대로 바인딩된다.

순서대로 바인딩하는 것은 편리하지만 잘못된 순서로 입력되면 오류가 발생할 수 있다. 이러한 문제를 보완하기 위해 JdbcTempate은 이름 기반 파라미터 바인딩 기능을 가진NamedParameterJdbcTemplate를 제공한다.

@Repository
public class CustomerNamedJdbcRepository implements CustomerRepository {
    private final NamedParameterJdbcTemplate jdbcTemplate;

    public CustomerNamedJdbcRepository(DataSource dataSource) {
        this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
    }

    @Override
    public void save(Customer customer) {
        String sql = "insert into customers(customer_id, name) values (:customerId, :name)";
        MapSqlParameterSource param = new MapSqlParameterSource()
                .addValue("customerId", customer.getCustomerId().toString())
                .addValue("name", customer.getName());
        jdbcTemplate.update(sql, param);
    }

    @Override
    public Optional<Customer> findById(UUID customerId) {
        String sql = "select * from customers where customer_id = :customerId";
        Map<String, Object> param = Map.of("customerId", customerId.toString());
        Customer customer = jdbcTemplate.queryForObject(sql, param, customerRowMapper());
        return Optional.ofNullable(customer);
    }

    @Override
    public List<Customer> findAll() {
        String sql = "select * from customers";
        return jdbcTemplate.query(sql, customerRowMapper());
    }

    @Override
    public void update(Customer customer) {
        String sql = "update customers set name = :name where customer_id = :customerId";
        MapSqlParameterSource param = new MapSqlParameterSource()
                .addValue("name", customer.getName())
                .addValue("customerId", customer.getCustomerId().toString());
        jdbcTemplate.update(sql, param);
    }

    @Override
    public void deleteAll() {
        String sql = "delete from customers";
        jdbcTemplate.update(sql, Map.of());
    }

    private RowMapper<Customer> customerRowMapper() {
        return (rs, rowNum) -> {
            UUID findCustomerId = UUID.fromString(rs.getString("customer_id"));
            String name = rs.getString("name");
            return new Customer(findCustomerId, name);
        };
    }
}

기존의 JdbcTemplate이 SQL에 ?로 파라미터를 받던 것과 달리 :파라미터이름으로 받고 있다. 그리고 두 번째 인수로 Map 또는 MapSqlParameterSource를 전달하고 있다.

2. 트랜잭션

트랜잭션이란 하나의 단위 작업을 수행하는데 있어서 해당 단위 작업을 구성하고 있는 동작들이 모두 성공하거나 실패해야 하는 최소한의 단위이다.

하나의 트랜잭션을 구성하는 모든 작업이 성공해서 데이터베이스에 정상 반영하는 것을 commit이라 한다. 반대로, 작업이 하나라도 실패하는 경우 작업 이전의 상태로 되돌리는 것을 rollback이라 한다.

트랜잭션은 ACID라 하는 네 가지 속성을 보장해야 한다.

원자성(Atomicity)

  • 하나의 트랜잭션을 구성하는 작업들은 모두 성공하거나 모두 실패해야 한다.

일관성(Consistency)

  • 트랜잭션 전과 후의 데이터베이스의 상태는 일관성을 유지해야 한다. 예를 들어 데이터베이스에서 정한 무결성 제약 조건을 항상 만족해야 한다.

격리성(Isolation)

  • 동시에 실행되는 트랜잭션이 서로 다른 트랜잭션의 작업에 영향을 미쳐서는 안 된다.

지속성(Durability)

  • 트랜잭션이 성공적으로 끝나면 그 결과는 데이터베이스에 영속적으로 저장되어야 한다. 재해가 발생하더라도 성공적으로 반영된 데이터는 복구할 수 있어야 한다.

'공부방' 카테고리의 다른 글

[TIL 07/03] 웹, 서블릿  (0) 2023.07.05
[TIL 06/30] 스프링 AOP, 스프링 트랜잭션  (0) 2023.07.04
[TIL 06/28] Connection Pool, DataSource, JdbcTemplate  (0) 2023.06.30
[TIL 06/27] JDBC  (0) 2023.06.30
[TIL 06/26] 테스트  (0) 2023.06.29