package com.example.aninbatis.executor;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import com.example.aninbatis.config.Configuration;
import com.example.aninbatis.config.MappedStatement;
import com.example.aninbatis.sqlsource.BoundSql;
import com.example.aninbatis.sqlsource.ParameterMapping;
import com.example.aninbatis.sqlsource.SqlSource;
/**
* 普通执行JDBC程序
*/
public class SimpleExecutor extends BaseExecutor {
@Override
public List<Object> queryFromDataBase(MappedStatement mappedStatement, Configuration configuration, Object param) {
List<Object> results = new ArrayList<>();
try {
// 获取连接
Connection connection = getConnection(configuration);
// 获取sql语句
BoundSql boundSql = getBoundSql(mappedStatement.getSqlSource(), param);
String statementType = mappedStatement.getStatementType();
// 使用mybatis的四大组件来优化
if ("PREPARED".equals(statementType)) {
// 创建Statement
PreparedStatement statement = createStatement(connection, boundSql.getSql());
System.out.println(" >>>>>>>>>>>>>> 执行sql:" + boundSql.getSql());
System.out.println(" >>>>>>>>>>>>>> 参数:" + param);
// 设置参数
handleParameter(statement, boundSql, param);
// 执行Statement
ResultSet resultSet = statement.executeQuery();
// 处理结果
handleResult(resultSet, mappedStatement, results);
}
} catch (Exception e) {
e.printStackTrace();
}
return results;
}
private void handleResult(ResultSet rs, MappedStatement mappedStatement, List<Object> results) throws Exception {
// 从结果集中一行一行的取数据
// 每一行数据,再一列一列的取数据(包括列的名称和列的值)
// 最终将获取到的每一列的值都映射到目标对象的指定属性中(列的名称和属性名称要一致)
Class<?> resultTypeClass = mappedStatement.getResultTypeClass();
while (rs.next()) {
// 要映射的结果目标对象
Object result = resultTypeClass.newInstance();
// 获取结果集的元数据(目的是取列的信息)
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 0; i < columnCount; i++) {
String columnName = metaData.getColumnName(i + 1);
Field field = resultTypeClass.getDeclaredField(columnName);
field.setAccessible(true);
field.set(result, rs.getObject(columnName));
}
results.add(result);
}
}
private void handleParameter(PreparedStatement statement, BoundSql boundSql, Object param) throws Exception {
// 判断入参的类型,如果是简单类型,直接处理
if (param instanceof Integer) {
statement.setObject(1, Integer.parseInt(param.toString()));
} else if (param instanceof String) {
statement.setObject(1, param.toString());
} else {
// 获取参数集合信息(#{}处理之后得到的参数信息)
// 如果是POJO类型,则根据参数信息里面的参数名称,去入参对象中获取对应的参数值
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
for (int i = 0; i < parameterMappings.size(); i++) {
Object valueToUser = null;
ParameterMapping parameterMapping = parameterMappings.get(i);
// #{}中的参数名称,也应该和POJO类型中的属性名称一直
String name = parameterMapping.getName();
// 使用反射获取指定name的值
Class<?> clazz = param.getClass();
// 获取指定名称的属性对象
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
valueToUser = field.get(param);
statement.setObject(i + 1, valueToUser);
}
}
}
private PreparedStatement createStatement(Connection connection, String sql) throws Exception {
PreparedStatement prepareStatement = connection.prepareStatement(sql);
return prepareStatement;
}
private BoundSql getBoundSql(SqlSource sqlSource, Object param) {
BoundSql boundSql = sqlSource.getBoundSql(param);
return boundSql;
}
private Connection getConnection(Configuration configuration) throws Exception {
DataSource dataSource = configuration.getDataSource();
Connection connection = dataSource.getConnection();
return connection;
}
}