JdbcTemplate

조승빈·2024년 10월 31일

Spring DB

목록 보기
1/8
post-thumbnail

JdbcTemplate는 스프링에서 데이터베이스 작업을 더 쉽게 수행할 수 있게 해주는 클래스이다.

JdbcTemplate의 장점

  1. 설정의 편리함:
    JdbcTemplate는 기본적으로 데이터베이스 설정을 한 번만 하면 다양한 CRUD 작업을 바로 할 수 있다. 데이터베이스 커넥션을 설정하고 처리하는 로직이 간소화되며, SQL 쿼리를 실행할 때마다 커넥션을 열고 닫는 코드가 필요하지 않아 편리하다.

  2. 반복 문제 해결:
    JdbcTemplate는 콜백 패턴을 활용해 반복 작업을 줄여준다. 예를 들어, 데이터베이스 연결을 열고 닫는 작업, 쿼리 실행 및 예외 처리와 같은 반복적인 코드를 콜백 패턴으로 처리하여 코드가 간결해진다.

JdbcTemplate의 단점

동적 SQL 처리의 어려움 :
JdbcTemplate는 기본적으로 SQL 쿼리를 템플릿 형식으로 사용할 때 동적 쿼리를 작성하기 어렵다.
예를 들어, 조건문에 따라 SQL의 일부를 수정해야 하는 경우 sql문을 직접 수정하는 방식으로 작성해야 하는데, 이는 코드가 복잡해지고 유지보수가 어려워질 수 있다.
-> MyBatis를 사용하면 sql을 직접 사용할 때 동적쿼리를 쉽게 작성할 수 있다.

예시 코드:

@Autowired
private JdbcTemplate jdbcTemplate;

public Long addUser(String name, String email) {
 String sql = "INSERT INTO users (name, email) VALUES (?, ?)";

 KeyHolder keyHolder = new GeneratedKeyHolder();  // KeyHolder 생성
 jdbcTemplate.update(connection -> {
     PreparedStatement ps = connection.prepareStatement(sql, new String[] {"id"});
     ps.setString(1, name);
     ps.setString(2, email);
     return ps;
 }, keyHolder);

 // 삽입된 레코드의 자동 생성된 키 값 반환
 return keyHolder.getKey().longValue();
}

KeyHolder : 데이터베이스에 새로운 레코드를 삽입할 때 자동 생성된 키 값을 쉽게 얻기 위해 사용하는 인터페이스
데이터를 저장할 때 데이터베이스에서 id를 대신 생성해주기 때문에 insert가 완료되어야 key 확인이 가능하기 때문에 사용한다.

이름 지정 파라미터

이름 지정 파라미터(named parameters)를 사용할 때, Spring의 NamedParameterJdbcTemplate를 통해 SQL 쿼리에서 가독성 높고 간편한 파라미터 매핑을 할 수 있다. NamedParameterJdbcTemplate는 세 가지 주요한 파라미터 타입을 지원한다.

  1. Map
    단순하게 키-값 쌍으로 파라미터를 전달할 때 사용한다.

  2. MapSqlParameterSource
    Map과 비슷하지만, SQL에서의 데이터 변환이나 타입 매핑 기능을 더 제공한다.

  3. BeanPropertySqlParameterSource
    Java Bean 규약에 따라, 객체의 속성을 자동으로 매핑하여 SQL에 전달한다. Java Bean 규약을 따르는 객체의 필드명을 SQL의 파라미터 이름과 일치시켜 자동 매핑하므로, 별도의 매핑 코드를 작성할 필요가 없다. 이로 인해 코드가 간결해지고 가독성이 높아진다.

    예시 코드:

// 예시 엔티티
public class Person {
    private int id;
    private String name;
    private int age;

    // 생성자, getter, setter 생략
}

public class NamedParameterExample {
    private NamedParameterJdbcTemplate jdbcTemplate;

    public NamedParameterExample(NamedParameterJdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    // 1. Map을 이용한 방법
    public void updatePersonWithMap(int id, String name) {
        String sql = "UPDATE person SET name = :name WHERE id = :id";
        
        Map<String, Object> params = new HashMap<>();
        params.put("id", id);
        params.put("name", name);
        
        jdbcTemplate.update(sql, params);
    }

    // 2. MapSqlParameterSource를 이용한 방법
    public void updatePersonWithMapSqlParameterSource(int id, String name) {
        String sql = "UPDATE person SET name = :name WHERE id = :id";
        
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("id", id);
        params.addValue("name", name);
        
        jdbcTemplate.update(sql, params);
    }

    // 3. BeanPropertySqlParameterSource를 이용한 방법
    public void updatePersonWithBeanPropertySqlParameterSource(Person person) {
        String sql = "UPDATE person SET name = :name, age = :age WHERE id = :id";
        
        BeanPropertySqlParameterSource params = new BeanPropertySqlParameterSource(person);
        
        jdbcTemplate.update(sql, params);
    }
}

관례의 불일치
java에서는 camelCase 표기법을 사용하고 데이터베이스에는 언더스코어를 사용하기 때문에 관례의 불일치가 있다.
BeanPropertyRowMapper는 데이터베이스의 snake_case 표기법을 Java의 camelCase 필드명으로 자동으로 변환해주는 기능을 제공한다. 이 기능 덕분에, SQL 조회 결과를 Java 객체에 쉽게 매핑할 수 있다.

SimpleJdbcInsert

보통 테이블에 데이터를 쉽게 추가할 수 있도록 설계되어 있으며, 주요 장점은 SQL 쿼리를 명시적으로 작성할 필요 없이 메서드 호출만으로도 데이터를 삽입할 수 있다는 것이다.
데이터베이스에서 자동으로 생성되는 기본 키(예: auto_increment 필드) 값을 삽입 후 받아올 수 있다. 이를 통해 방금 삽입한 데이터의 키를 손쉽게 조회할 수 있다.

예시 코드:

public class PersonRepository {
    private final SimpleJdbcInsert jdbcInsert;

    public PersonRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcInsert = new SimpleJdbcInsert(jdbcTemplate)
                .withTableName("person")
                .usingGeneratedKeyColumns("id");  // 자동 생성 키를 사용하는 경우 설정
    }

    // 1. Map을 사용한 데이터 삽입
    public Number insertPersonUsingMap(String name, int age) {
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("name", name);
        parameters.put("age", age);
        
        return jdbcInsert.executeAndReturnKey(parameters);  // 자동 생성된 키 반환
    }

    // 2. Java Bean 객체를 사용한 데이터 삽입
    public Number insertPersonUsingBean(Person person) {
        BeanPropertySqlParameterSource params = new BeanPropertySqlParameterSource(person);
        
        return jdbcInsert.executeAndReturnKey(params);  // 자동 생성된 키 반환
    }
}
profile
평범

0개의 댓글