NamedParameterJdbcTemplate
Spring에서는 데이터에 접근하는 기능으로 JdbcTemplate
을 구현한 다양한 구현체를 갖고 있습니다.
이번 포스팅에서는 JdbcTemplate
를 구현한 구현체인 NamedParameterJdbcTemplate
를 사용할 때 얻을 수 있는 편리함에 대해 글을 작성해보고자 합니다.
NamedParameterJdbcTemplate
는 Jdbc를 사용할 때 생기는 ?
코드를 대체하고자 래핑한 클래스입니다. NamedParameterJdbcTemplate
가 sql 쿼리를 만드는 전략은 추가해야 할 파라미터가 많을 때 코드 작성을 정말 편리하게 만들어 줍니다.
직접 코드를 작성해보면 이 편리함을 느낄 수 있습니다.
간단하게 우테코 crew들의 정보를 관리할 수 있는 table을 만들고 entity를 생성해보겠습니다.
public class Crew {
private Long id;
private String name;
private String nickname;
private String phoneNumber;
public Crew(Long id, String name, String nickname, String phoneNumber) {
this.id = id;
this.name = name;
this.nickname = nickname;
this.phoneNumber = phoneNumber;
}
public Crew(String name, String nickname, String phoneNumber) {
this.name = name;
this.nickname = nickname;
this.phoneNumber = phoneNumber;
}
// .. getter 생략
}
그리고 NamedParameterJdbcTemplate
를 사용하는 Repository 클래스를 하나 생성합니다.
@Repository
public class CrewRepository {
private final NamedParameterJdbcTemplate jdbcTemplate;
public CrewRepository(NamedParameterJdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
이제 크루 정보를 기입하고 여러 정보에 따라 크루의 데이터를 가져오는 코드를 작성해보겠습니다.
public void create(Crew crew) {
String sql = "insert into crew (name, nickname, phone_number) values (:name, :nickname, :phoneNumber)";
SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(crew);
jdbcTemplate.update(sql, namedParameters);
}
일반 jdbcTemplate
과 차이가 느껴지나요?
일반적인 경우에는 아래와 같은 순서로 sql 쿼리를 작성하는 데요,
- 입력하고자 하는 파라미터를 ?로 작성한다.
- 순서에 맞게 ?에 값을 할당한다.
NamedParameterJdbcTemplate
를 사용하는 경우에는 위 코드처럼 SqlParameterSource의 구현체를 사용하여 간단하게 입력 파라미터를 완성시킵니다.
어떻게 완성할 수 있을까요?
/**
* Create a new BeanPropertySqlParameterSource for the given bean.
* @param object the bean instance to wrap
*/
public BeanPropertySqlParameterSource(Object object) {
this.beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(object);
}
위 구현체는 내부적으로 java beans에 접근하여 파라미터의 이름과 동일하게 작성된 field의 getter가 존재한다면 해당 값을 가져와 입력 파라미터에 할당할 수 있습니다.
덕분에 웹요청으로 들어온 값을 Dto 하나로 생성하여 쉽게 option에 따른 계산로직을 수행할 수도 있습니다.
public Crew findByOption(CrewDto crewDto) {
String sql = createFilterSelectSql(crewDto);
log.info("SQL query = {}",sql);
SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(crewDto);
return jdbcTemplate.queryForObject(sql, namedParameters, (rs, rowNum) -> {
return new Crew(rs.getLong("id"),
rs.getString("name"),
rs.getString("nickname"),
rs.getString("phone_number"));
});
}
private String createFilterSelectSql(CrewDto crewDto) {
StringBuilder stringBuilder = new StringBuilder();
String sql = "select * from crew";
stringBuilder.append(sql);
String keyword = " where";
if (!crewDto.isNameNull()) {
keyword = changePrefixKeyword(sql);
stringBuilder.append(keyword)
.append(" name = :name");
}
if (!crewDto.isNicknameNull()) {
keyword = changePrefixKeyword(sql);
stringBuilder.append(keyword)
.append(" nickname = :nickname");
}
if (!crewDto.isPhoneNumberNull()) {
keyword = changePrefixKeyword(sql);
stringBuilder.append(keyword)
.append(" phone_number = :phoneNumber");
}
return stringBuilder.toString();
}
SqlParamterSource
를 이용한다면 자바 빈즈를 사용해서 쉽게 입력 파라미터를 사용할 수 있습니다 ^^
'우아한테크코스 4기 > 레벨2' 카테고리의 다른 글
[SQL] 페이징 구현하기 (2) | 2022.05.07 |
---|---|
[Spring] Transaction 추상화, 동기화 (0) | 2022.04.27 |
[Spring] 컨트롤러 테스트 시 한글 깨짐 문제 해결 (0) | 2022.04.24 |
[Spring] MockMvc 를 이용한 컨트롤러 테스트 (0) | 2022.04.23 |
[Spring] Spring Boot에서 트랜잭션 사용하기 (1) | 2022.04.20 |