İlkbaharda güzel bir örnekle karşılaştım. Çerçeve, çeşitli veritabanı işlemlerini tek tip bir şekilde ele almak için yöntemin içindeki yerel sınıf tanımları kavramını kullanıyor.
Bunun gibi bir kodunuz olduğunu varsayalım:
JdbcTemplate jdbcOperations = new JdbcTemplate(this.myDataSource);
jdbcOperations.execute("call my_stored_procedure()")
jdbcOperations.query(queryToRun, new MyCustomRowMapper(), withInputParams);
jdbcOperations.update(queryToRun, withInputParams);
İlk olarak execute () uygulamasına bakalım:
@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());
}
Lütfen son satıra dikkat edin. Spring, bu "numarayı" diğer yöntemler için de yapar:
//uses local class QueryStatementCallback implements StatementCallback<T>, SqlProvider
jdbcOperations.query(...)
//uses local class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider
jdbcOperations.update(...)
Yerel sınıflarla "hile", çerçevenin StatementCallback arabirimi aracılığıyla bu sınıfları kabul eden tek bir yöntemde tüm bu senaryolarla ilgilenmesine izin verir. Bu tek yöntem, eylemler (yürütme, güncelleme) ve etraflarındaki ortak işlemler (örn. Yürütme, bağlantı yönetimi, hata çevirisi ve dbms konsol çıkışı) arasında bir köprü görevi görür.
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());
}
}