MyBatis提供了一个用于操作数据库的SqlRunner工具类,对JDBC做了很好的封装。结合工具类SQL,能够很方便地通过Java代码执行SQL语句并检索SQL执行结果。如下示例代码所示:
String sql = new SQL()
.SELECT("*")
.FROM("user_info")
.WHERE("id = #{id}", "name = #{name}")
.toString();
Connection connection = DriverManager.getConnection("数据库连接");
SqlRunner sqlRunner = new SqlRunner(connection);
Map<String, Object> result = sqlRunner.selectOne(sql, 1, "Jason");
SqlRunner不仅提供了上述selectOne()方法,还提供了:
这里以最具代表性的selectAll(String sql, Object… args)方法为例,来进一步剖析SqlRunner类源代码逻辑。
public List<Map<String, Object>> selectAll(String sql, Object... args) throws SQLException {
try (PreparedStatement ps = connection.prepareStatement(sql)) {
setParameters(ps, args);
try (ResultSet rs = ps.executeQuery()) {
return getResults(rs);
}
}
}
如源代码所示,selectAll详细处理逻辑如下,
在通过Connection对象获取到PreparedStatement对象后,首先调用setParameters方法来对SQL语句中的占位符进行赋值,源代码详情如下,
private void setParameters(PreparedStatement ps, Object... args) throws SQLException {
for (int i = 0, n = args.length; i < n; i++) {
if (args[i] == null) {
throw new SQLException("SqlRunner requires an instance of Null to represent typed null values for JDBC compatibility");
} else if (args[i] instanceof Null) {
((Null) args[i]).getTypeHandler().setParameter(ps, i + 1, null, ((Null) args[i]).getJdbcType());
} else {
TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(args[i].getClass());
if (typeHandler == null) {
throw new SQLException("SqlRunner could not find a TypeHandler instance for " + args[i].getClass());
} else {
typeHandler.setParameter(ps, i + 1, args[i], null);
}
}
}
}
如源代码所示,setParameters方法首先会对可变参数args进行遍历,并将得到的值进行如下处理:
在组装好SQL语句,并通过PreparedStatement的executeQuery()方法获得查询结果后,此时就该getResults大显身手处理结果集。
private List<Map<String, Object>> getResults(ResultSet rs) throws SQLException {
List<Map<String, Object>> list = new ArrayList<>();
List<String> columns = new ArrayList<>();
List<TypeHandler<?>> typeHandlers = new ArrayList<>();
// 获取ResultSetMetaData对象,用于遍历结果
ResultSetMetaData rsmd = rs.getMetaData();
for (int i = 0, n = rsmd.getColumnCount(); i < n; i++) {
columns.add(rsmd.getColumnLabel(i + 1));
try {
Class<?> type = Resources.classForName(rsmd.getColumnClassName(i + 1));
TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(type);
if (typeHandler == null) {
typeHandler = typeHandlerRegistry.getTypeHandler(Object.class);
}
typeHandlers.add(typeHandler);
} catch (Exception e) {
typeHandlers.add(typeHandlerRegistry.getTypeHandler(Object.class));
}
}
while (rs.next()) {
Map<String, Object> row = new HashMap<>();
for (int i = 0, n = columns.size(); i < n; i++) {
String name = columns.get(i);
TypeHandler<?> handler = typeHandlers.get(i);
row.put(name.toUpperCase(Locale.ENGLISH), handler.getResult(rs, name));
}
list.add(row);
}
return list;
}
如上述源代码所示,