-
Notifications
You must be signed in to change notification settings - Fork 300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[JDBC 라이브러리 구현하기 - 2단계] 제이미(임정수) 미션 제출합니다. #432
Changes from 8 commits
47d7909
4b80842
23e8180
00768b5
f2d7474
18b497a
f9889f7
1861cfe
eec4c97
73d0bfb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,9 @@ | ||
package org.springframework.jdbc.core; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.jdbc.core.exception.EmptyResultDataAccessException; | ||
import org.springframework.jdbc.core.exception.IncorrectResultSizeDataAccessException; | ||
|
||
import javax.sql.DataSource; | ||
import java.sql.Connection; | ||
import java.sql.PreparedStatement; | ||
import java.sql.ResultSet; | ||
import java.sql.SQLException; | ||
|
@@ -13,83 +12,67 @@ | |
|
||
public class JdbcTemplate { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class); | ||
public static final int MAX_RESULT_SIZE = 1; | ||
public static final int FIRST_INDEX = 0; | ||
|
||
private final DataSource dataSource; | ||
private final PreparedStatementExecutor preparedStatementExecutor; | ||
|
||
public JdbcTemplate(final DataSource dataSource) { | ||
this.dataSource = dataSource; | ||
this.preparedStatementExecutor = new PreparedStatementExecutor(dataSource); | ||
} | ||
|
||
public int update(final String sql, final Object... args) { | ||
try ( | ||
final Connection conn = dataSource.getConnection(); | ||
final PreparedStatement pstmt = conn.prepareStatement(sql) | ||
) { | ||
setArguments(pstmt, args); | ||
|
||
log.debug("query : {}", sql); | ||
|
||
return pstmt.executeUpdate(); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
} | ||
return preparedStatementExecutor.execute(PreparedStatement::executeUpdate, sql, args); | ||
} | ||
|
||
private static void setArguments(final PreparedStatement pstmt, final Object[] args) throws SQLException { | ||
for (int i = 0; i < args.length; i++) { | ||
final int parameterIndex = i + 1; | ||
pstmt.setObject(parameterIndex, args[i]); | ||
} | ||
public <T> T queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... args) { | ||
return preparedStatementExecutor.execute( | ||
pstmt -> { | ||
final ResultSet rs = pstmt.executeQuery(); | ||
final List<T> results = getResults(rowMapper, rs); | ||
|
||
return getSingleResult(results); | ||
}, sql, args | ||
Comment on lines
+30
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 익명 함수를 잘 사용해주셨네요 ! |
||
); | ||
} | ||
|
||
public <T> T queryForObject(final String sql, final RowMapper<T> rowMapper, final Object... args) { | ||
try ( | ||
final Connection conn = dataSource.getConnection(); | ||
final PreparedStatement pstmt = conn.prepareStatement(sql) | ||
) { | ||
setArguments(pstmt, args); | ||
ResultSet rs = pstmt.executeQuery(); | ||
|
||
log.debug("query : {}", sql); | ||
|
||
return calculateResult(rowMapper, rs); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
private <T> List<T> getResults(final RowMapper<T> rowMapper, final ResultSet rs) throws SQLException { | ||
final List<T> results = new ArrayList<>(); | ||
|
||
while (rs.next()) { | ||
final T result = calculateResult(rowMapper, rs); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. while(rs.next())로 resultSet의 row가 있는지 확인한 상태인데 다시 바로 rowMapper.mapRow(rs)를 실행시키면 어떤 문제가 발생하나요 ?!😁 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헉... 아무 문제도 없습니다... 🫢 |
||
results.add(result); | ||
} | ||
|
||
return results; | ||
} | ||
|
||
private static <T> T calculateResult(final RowMapper<T> rowMapper, final ResultSet rs) throws SQLException { | ||
private <T> T calculateResult(final RowMapper<T> rowMapper, final ResultSet rs) throws SQLException { | ||
if (rs.next()) { | ||
return rowMapper.mapRow(rs, rs.getRow()); | ||
return rowMapper.mapRow(rs); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
public <T> List<T> query(final String sql, final RowMapper<T> rowMapper) { | ||
try ( | ||
final Connection conn = dataSource.getConnection(); | ||
final PreparedStatement pstmt = conn.prepareStatement(sql) | ||
) { | ||
ResultSet rs = pstmt.executeQuery(); | ||
|
||
log.debug("query : {}", sql); | ||
|
||
return getResults(rowMapper, rs); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
private <T> T getSingleResult(final List<T> results) { | ||
if (results.isEmpty()) { | ||
throw new EmptyResultDataAccessException("조회된 결과가 존재하지 않습니다."); | ||
} | ||
if (results.size() > MAX_RESULT_SIZE) { | ||
throw new IncorrectResultSizeDataAccessException("조회된 결과의 개수가 적절하지 않습니다."); | ||
} | ||
} | ||
|
||
private static <T> List<T> getResults(final RowMapper<T> rowMapper, final ResultSet rs) throws SQLException { | ||
List<T> results = new ArrayList<>(); | ||
return results.get(FIRST_INDEX); | ||
} | ||
|
||
while (rs.next()) { | ||
final T result = calculateResult(rowMapper, rs); | ||
results.add(result); | ||
} | ||
public <T> List<T> query(final String sql, final RowMapper<T> rowMapper) { | ||
return preparedStatementExecutor.execute( | ||
pstmt -> { | ||
final ResultSet rs = pstmt.executeQuery(); | ||
|
||
return results; | ||
return getResults(rowMapper, rs); | ||
}, sql | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.springframework.jdbc.core; | ||
|
||
import java.sql.PreparedStatement; | ||
import java.sql.SQLException; | ||
|
||
@FunctionalInterface | ||
public interface PreparedStatementExecuteStrategy<T> { | ||
|
||
T strategy(final PreparedStatement pstmt) throws SQLException; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.springframework.jdbc.core; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import javax.sql.DataSource; | ||
import java.sql.Connection; | ||
import java.sql.PreparedStatement; | ||
import java.sql.SQLException; | ||
|
||
public class PreparedStatementExecutor { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(JdbcTemplate.class); | ||
|
||
private final DataSource dataSource; | ||
|
||
public PreparedStatementExecutor(final DataSource dataSource) { | ||
this.dataSource = dataSource; | ||
} | ||
|
||
public <T> T execute(final PreparedStatementExecuteStrategy<T> executeStrategy, final String sql, final Object... args) { | ||
try ( | ||
final Connection conn = dataSource.getConnection(); | ||
final PreparedStatement pstmt = conn.prepareStatement(sql) | ||
) { | ||
setArguments(pstmt, args); | ||
|
||
log.debug("query : {}", sql); | ||
|
||
return executeStrategy.strategy(pstmt); | ||
} catch (SQLException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private void setArguments(final PreparedStatement pstmt, final Object[] args) throws SQLException { | ||
for (int i = 0; i < args.length; i++) { | ||
final int parameterIndex = i + 1; | ||
pstmt.setObject(parameterIndex, args[i]); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.springframework.jdbc.core.exception; | ||
|
||
import org.springframework.dao.DataAccessException; | ||
|
||
public class EmptyResultDataAccessException extends DataAccessException { | ||
|
||
public EmptyResultDataAccessException(final String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.springframework.jdbc.core.exception; | ||
|
||
import org.springframework.dao.DataAccessException; | ||
|
||
public class IncorrectResultSizeDataAccessException extends DataAccessException { | ||
|
||
public IncorrectResultSizeDataAccessException(final String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.springframework.jdbc.core.exception; | ||
|
||
public class ResultSetOverflowException extends IllegalArgumentException { | ||
|
||
public ResultSetOverflowException(final String message) { | ||
super(message); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍