在之前,我寫過一篇【設計】設計一個web版的數據庫管理平臺后端精要 的文章,文章講了一個web版數據庫管理平臺的實現思路及主要代碼。
最近,我看了下Mybatis的源碼,覺得Mybatis的分層架構挺好,所以想到了完善下web版數據庫管理平臺中,關于sql查詢的功能。
在上期文章中,關于sql的執行,代碼是最簡單的
// 執行SQL
jdbcTemplate.execute(sql);
對于sql查詢功能來說,這是遠遠不夠的,sql查詢需要查詢出數據庫中的結果,并顯示在網頁上。這里我們比Mybatis簡單,我們不需要實現結果與java類型的映射,只是顯示出來就好。
網上有個圖片(原圖地址,如有侵權,請聯系我),很好的反應了我即將要做的事情
方案
也就是說,我要將原來直接執行sql的方式進行解耦,改為調用SQL執行器去執行。
參考Mybatis,我們添加了
SqlSession│├── Configuration (配置中心)│└── Executor (執行器)│├── StatementHandler (語句處理器)│└── ResultSetHandler (結果集處理器)
以下是本次完善的類圖。
類圖說明:
- 核心類關系:
- SqlSession 是入口類,包含Configuration和Executor
- Executor 接口定義了執行SQL的核心方法
- SimpleExecutor 是基礎實現,使用StatementHandler執行SQL
- 執行流程相關類:
- StatementHandler 負責SQL語句準備和執行
- SimpleStatementHandler 是基礎實現,使用PreparedStatement
- ResultSetHandler 負責結果集處理
- MapResultSetHandler 將ResultSet轉為List
- 配置類:
- Configuration 持有數據源等配置信息
- 依賴關系:
- 實線箭頭表示組合關系(強擁有)
- 虛線箭頭表示依賴關系(臨時使用)
- 空心三角箭頭表示接口實現
詳細設計
Configuration 配置類
public class Configuration {private DataSource dataSource;private boolean cacheEnabled = false;// 其他配置項...public Configuration(DataSource dataSource) {this.dataSource = dataSource;}// getters and setters...
}
SqlSession 實現
public class SqlSession {private final Configuration configuration;private final Executor executor;public SqlSession(Configuration configuration) {this.configuration = configuration;this.executor = new SimpleExecutor(configuration);}public List<Map<String, Object>> selectList(String sql, Object... parameters) {return executor.query(sql, parameters);}public void close() {executor.close();}
}
Executor 執行器
public interface Executor {List<Map<String, Object>> query(String sql, Object... parameters);void close();
}public class SimpleExecutor implements Executor {private final Configuration configuration;private Connection connection;public SimpleExecutor(Configuration configuration) {this.configuration = configuration;}@Overridepublic List<Map<String, Object>> query(String sql, Object... parameters) {try {StatementHandler statementHandler = new SimpleStatementHandler(configuration);return statementHandler.query(sql, parameters);} catch (SQLException e) {throw new RuntimeException("Error executing query: " + sql, e);}}@Overridepublic void close() {if (connection != null) {try {connection.close();} catch (SQLException e) {// ignore}}}
}
StatementHandler 語句處理器
public interface StatementHandler {List<Map<String, Object>> query(String sql, Object... parameters) throws SQLException;
}public class SimpleStatementHandler implements StatementHandler {private final Configuration configuration;private final ResultSetHandler resultSetHandler;public SimpleStatementHandler(Configuration configuration) {this.configuration = configuration;this.resultSetHandler = new MapResultSetHandler();}@Overridepublic List<Map<String, Object>> query(String sql, Object... parameters) throws SQLException {Connection connection = null;PreparedStatement stmt = null;ResultSet rs = null;try {connection = configuration.getDataSource().getConnection();stmt = connection.prepareStatement(sql);// 設置參數for (int i = 0; i < parameters.length; i++) {stmt.setObject(i + 1, parameters[i]);}rs = stmt.executeQuery();return resultSetHandler.handleResultSets(rs);} finally {if (rs != null) {try {rs.close();} catch (SQLException e) {// ignore}}if (stmt != null) {try {stmt.close();} catch (SQLException e) {// ignore}}if (connection != null) {try {connection.close();} catch (SQLException e) {// ignore}}}}
}
ResultSetHandler 結果集處理器
public interface ResultSetHandler {List<Map<String, Object>> handleResultSets(ResultSet rs) throws SQLException;
}public class MapResultSetHandler implements ResultSetHandler {@Overridepublic List<Map<String, Object>> handleResultSets(ResultSet rs) throws SQLException {List<Map<String, Object>> resultList = new ArrayList<>();ResultSetMetaData metaData = rs.getMetaData();int columnCount = metaData.getColumnCount();while (rs.next()) {Map<String, Object> row = new LinkedHashMap<>();for (int i = 1; i <= columnCount; i++) {String columnName = metaData.getColumnLabel(i);if (columnName == null || columnName.isEmpty()) {columnName = metaData.getColumnName(i);}row.put(columnName, rs.getObject(i));}resultList.add(row);}return resultList;}
}
使用示例
// 初始化配置
DataSource dataSource = ... // 創建數據源
Configuration configuration = new Configuration(dataSource);// 創建SqlSession
try (SqlSession sqlSession = new SqlSession(configuration)) {// 執行查詢List<Map<String, Object>> result = sqlSession.selectList("SELECT * FROM users WHERE age > ?", 18);// 處理結果for (Map<String, Object> row : result) {System.out.println(row);}
}