在之前,我写过一篇【设计】设计一个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);}
}