[JDBC] 단일 Select을 위한 방법들
Line
id bigint auto_increment not null,
name varchar(255) not null unique,
color varchar(20) not null,
primary key(id)
다음과 같은 Line 테이블이 있다.
select * from line where name = ? 다음과 같은 쿼리문의 결과값을 받아오려는 메소드를 만든다고 한다.
public Line findLineByName(String name) {
String sql = "select * from line where name = ?";
return jdbcTemplate.queryForObject(sql, lineRowMapper(), "1호선");
}
private RowMapper<Line> lineRowMapper() {
return (rs, rowNum) -> new Line(
rs.getLong("id"),
rs.getString("name"),
rs.gwetSTring("color")
);
}
다음과 같이 확인할 수 있을 것이다.
이번에 내가 글을 쓴 이유는 다음과 같다.
만약 위의 경우에서 결과값이 0개거나 2개 이상이면 예외가 발생할 것이다. 각각, EmptyResultDataAccessException과 IncorrectResultSizeDataAccessException이 발생하게 된다(전자의 예외는 후자의 예외를 상속받고 있다).
해당 예외를 잡아줘서 null을 던져주던가 해야하는데 그게 싫어서 Optional을 사용한다고 가정하자.
public Optional<Line> findLineByName(String name) {
String sql = "select * from line where name = ?";
try{
return Optional.ofNullable(jdbcTemplate.queryForObject(sql, lineRowMapper(), "1호선"));
} catch(IncorrectResultSizeDataAccessException e) {
return Optional.empty();
}
}
public Optional<Line> findLineByName(String name) {
String sql = "select * from line where name = ?";
return jdbcTemplate.query(sql, lineRowMapper(), "1호선").stream().findAny();
}
다음과 같은 방식으로 사용할 수 있을 것이다.
전자의 방법은 queryForObject를 사용한 방식이다. 값을 제대로 찾으면 Optional.ofNullable()로 감싸서 리턴하지만 그 값이 0개나 2개 이상인 경우 따로 예외를 잡아서 Optional.empty()를 반환해주고 있다.
query 방식은 List로 반환을 받는다. 이를 스트림으로 돌려서 아무거나 찾은 후에 리턴을 한다. 만약 찾지 못한 경우에는 Optional.empty()를 반환하게 된다.
가독성 측면에서는 후자가 훨 좋아보인다. 전자의 방법은 결과값의 개수가 딱 1개일 때에는 제대로 리턴하고 그 외에는 예외가 터지기 때문에 따로 잡아줘야 한다. 후자의 방법은 0,1개 일 때에는 적절하지만 2개 이상일 때에는 어떤 값을 찾아서 리턴해줄지 알 수 없다. 그리고 애초에 단일 건을 조회하기 위한 메소드가 아니기도 하다.
이렇게 장단점이 있다. 어떤 것을 쓰든 취향껏 사용하면 될 것 같다. 추가로 다음과 같은 방법도 있다.
public Line findLineByName(String name) {
String sql = "select * from line where name = ?";
List<Line> lines = jdbcTemplate.query(sql, lineRowMapper(), "1호선");
Line line = DataAccessUtils.singleResult(lines);
return line;
}
DataAccessUtils.singleResult(Collection)이 바로 그 방법이다.
query메소드를 사용했는데 단일 행이 나올 것이라고 예상되는 구문을 Collection 타입을 파라미터로 받는 singleResult메소드에 넣어주었다. 파라미터의 사이즈를 체크해서 0이면 null을 리턴하고 2개 이상이면 IncorrectResultSizeDataAccessException를 리턴한다. Optional형식을 사용하지 않고 단일 객체를 리턴하는데 query를 사용했을 경우에 이용할 수 있겠다.
여러가지 방법을 살펴봤는데 상황에 맞게끔 적절히 사용하는 것이 좋다고 생각한다.
'Java' 카테고리의 다른 글
| [Java] CountDownLatch, Semaphore, CyclicBarrier 에 대해 (0) | 2021.09.06 |
|---|---|
| [Java] OutputStream, InputStream, File 간단 사용법 정리 (0) | 2021.09.05 |
| [Java] 템플릿 메서드 패턴, 팩토리 메서드 패턴, 추상 팩토리 패턴 (0) | 2021.04.27 |
| [Java] try-with-resources 에 대해 (0) | 2021.04.06 |
| [Java] Arrays.asList와 List.of의 차이점에 대해 (0) | 2021.03.21 |