Repository는 jdbc 처리가 이루어지는 곳으로, 데이터 처리를 구현하며 코드 리뷰받은 내용을 정리하려 한다.
1) JdbcTemplate 사용전
2) JdbcTemplate 사용후
@Repository
public class JdbcUserRepository {
private NamedParameterJdbcTemplate jdbc;
private SimpleJdbcInsert insertAction;
public UserDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
this.rowMapper = new BeanPropertyRowMapper<User>(User.class);
this.insertAction = new SimpleJdbcInsert(dataSource)
.withTableName("USER")
.usingColumns("EMAIL", "PASSWD")
.usingGeneratedKeyColumns("seq");
// usingColumns 함수:
// SimpleJdbcInsert시 사용할 컬럼을 지정.
// 그렇지 않으면 User 모든 컬럼을 insert 쿼리 value에 넣으므로 param에 없는 컬럼은 null이 됨.
}
@Override
public List<User> selectUsersAll() {
return jdbc.query("SELECT SEQ, EMAIL, PASSWD , LOGIN_COUNT , LAST_LOGIN_AT , CREATE_AT FROM USER ORDER BY SEQ", Collections.emptyMap(), rowMapper);
}
@Override
public User selectUserById(Long seq) {
Map<String, Object> params = new HashMap<>();
params.put("seq", seq);
return jdbc.queryForObject("SELECT SEQ, EMAIL, PASSWD, LOGIN_COUNT, LAST_LOGIN_AT, CREATE_AT FROM USER WHERE SEQ = ? ORDER BY SEQ", params, rowMapper);
}
@Override
public SignupResponse insert(SignupRequest signupRequest) {
SqlParameterSource params = new BeanPropertySqlParameterSource(signupRequest);
return insertAction.executeAndReturnKey(params).longValue();
}
}
@Repository
public class JdbcUserRepository implements UserRepository {
private final JdbcTemplate jdbcTemplate;
private final MessageSource messageSource;
public JdbcUserRepository(JdbcTemplate jdbcTemplate, MessageSource messageSource) {
this.jdbcTemplate = jdbcTemplate;
this.messageSource = messageSource;
}
@Override
public List<User> findAll() {
List<User> users = jdbcTemplate.query("SELECT SEQ, EMAIL, PASSWD , LOGIN_COUNT , LAST_LOGIN_AT , CREATE_AT FROM USER ORDER BY SEQ", userMapper);
return !users.isEmpty() ? users : null;
}
@Override
public User findById(Long seq) {
try {
return jdbcTemplate.queryForObject("SELECT SEQ, EMAIL, PASSWD, LOGIN_COUNT, LAST_LOGIN_AT, CREATE_AT FROM USER WHERE SEQ = ? ORDER BY SEQ", new Object[]{seq}, userMapper);
} catch(EmptyResultDataAccessException e) {
e.printStackTrace();
return null;
}
}
@Override
public SignupResponse join(SignupRequest signupRequest) {
return jdbcTemplate.update("INSERT INTO USER(EMAIL,PASSWD,CREATE_AT) VALUES(?,?,?)", new Object[]{signupRequest.getPrincipal(),signupRequest.getCredentials(), new Date() }) > 0 ?
new SignupResponse(true, messageSource.getMessage("insert.response.success", new Object[]{}, Locale.KOREA))
: new SignupResponse(false, messageSource.getMessage("insert.response.failure", new Object[]{}, Locale.KOREA));
}
// 맵퍼 람다 처리
static RowMapper<User> userMapper = (rs, rowNum) -> new User( rs.getLong("SEQ"),
rs.getString("EMAIL"),
rs.getString("PASSWD"),
rs.getInt("LOGIN_COUNT"),
rs.getDate("LAST_LOGIN_AT"),
rs.getDate("CREATE_AT"));
}
이를 구현하면서 Spring-Jdbc 기초를 한번 다시 되짚어보게 되었다.
Spring Boot 를 사용하면서 이전에 Spring Framework에서 구현할 때보다 훨씬 생산성 높은 코드 작성이 가능하다고 느껴졌다. DataSource도 주입받지 않고, application.yml 에 db 정보를 작성하여 Spring boot Auto-Configuration 기능으로 받아와 사용할 수 있었다. (@EnableAutoConfiguration)
그리고 이전에 insert, select query를 작성하기 위해 주입해야할 클래스가 많았다.
(Spring 에도 있었지만) 이번 기회로 JdbcTemplate 클래스를 처음 사용해보면서 이를 활용하여 꽤나 쉽게(?) Repository를 작성할 수 있었다. JPA를 함께 공부하고 있는데 Repository를 interface를 생성하는 이유와 함수의 이름도 JPA에서 사용하는 그대로 써보기 위해 노력했다.
확실히 이전보다 직관성 높은 코드 작성과 효율적인 코딩이 가능해졌다고 느낄 수 있었다.
하지만 전혀 개념을 알지 못하고 사용하면 후에 문제가 생겼을 때, 원인 파악이 어려울 거라 생각한다. 지금 많이 삽질 하자