저는 봄에 좋은 예를 보았습니다. 프레임 워크는 메서드 내부의 로컬 클래스 정의 개념을 사용하여 다양한 데이터베이스 작업을 일관된 방식으로 처리합니다.
다음과 같은 코드가 있다고 가정합니다.
JdbcTemplate jdbcOperations = new JdbcTemplate(this.myDataSource);
jdbcOperations.execute("call my_stored_procedure()")
jdbcOperations.query(queryToRun, new MyCustomRowMapper(), withInputParams);
jdbcOperations.update(queryToRun, withInputParams);
먼저 execute () 구현을 살펴 보겠습니다.
@Override
public void execute(final String sql) throws DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL statement [" + sql + "]");
}
/**
* Callback to execute the statement.
(can access method local state like sql input parameter)
*/
class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
@Override
@Nullable
public Object doInStatement(Statement stmt) throws SQLException {
stmt.execute(sql);
return null;
}
@Override
public String getSql() {
return sql;
}
}
//transforms method input into a functional Object
execute(new ExecuteStatementCallback());
}
마지막 줄을 참고하십시오. Spring은 나머지 메소드에 대해서도 정확한 "트릭"을 수행합니다.
//uses local class QueryStatementCallback implements StatementCallback<T>, SqlProvider
jdbcOperations.query(...)
//uses local class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider
jdbcOperations.update(...)
로컬 클래스의 "트릭"을 통해 프레임 워크는 StatementCallback 인터페이스를 통해 해당 클래스를 허용하는 단일 메서드에서 이러한 모든 시나리오를 처리 할 수 있습니다. 이 단일 방법은 작업 (실행, 업데이트)과 작업 (예 : 실행, 연결 관리, 오류 변환 및 dbms 콘솔 출력) 사이의 다리 역할을합니다.
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(obtainDataSource());
Statement stmt = null;
try {
stmt = con.createStatement();
applyStatementSettings(stmt);
//
T result = action.doInStatement(stmt);
handleWarnings(stmt);
return result;
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
String sql = getSql(action);
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw translateException("StatementCallback", sql, ex);
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}