1. package com.example.aninbatis.executor;
    2. import java.lang.reflect.Field;
    3. import java.sql.Connection;
    4. import java.sql.PreparedStatement;
    5. import java.sql.ResultSet;
    6. import java.sql.ResultSetMetaData;
    7. import java.util.ArrayList;
    8. import java.util.List;
    9. import javax.sql.DataSource;
    10. import com.example.aninbatis.config.Configuration;
    11. import com.example.aninbatis.config.MappedStatement;
    12. import com.example.aninbatis.sqlsource.BoundSql;
    13. import com.example.aninbatis.sqlsource.ParameterMapping;
    14. import com.example.aninbatis.sqlsource.SqlSource;
    15. /**
    16. * 普通执行JDBC程序
    17. */
    18. public class SimpleExecutor extends BaseExecutor {
    19. @Override
    20. public List<Object> queryFromDataBase(MappedStatement mappedStatement, Configuration configuration, Object param) {
    21. List<Object> results = new ArrayList<>();
    22. try {
    23. // 获取连接
    24. Connection connection = getConnection(configuration);
    25. // 获取sql语句
    26. BoundSql boundSql = getBoundSql(mappedStatement.getSqlSource(), param);
    27. String statementType = mappedStatement.getStatementType();
    28. // 使用mybatis的四大组件来优化
    29. if ("PREPARED".equals(statementType)) {
    30. // 创建Statement
    31. PreparedStatement statement = createStatement(connection, boundSql.getSql());
    32. System.out.println(" >>>>>>>>>>>>>> 执行sql:" + boundSql.getSql());
    33. System.out.println(" >>>>>>>>>>>>>> 参数:" + param);
    34. // 设置参数
    35. handleParameter(statement, boundSql, param);
    36. // 执行Statement
    37. ResultSet resultSet = statement.executeQuery();
    38. // 处理结果
    39. handleResult(resultSet, mappedStatement, results);
    40. }
    41. } catch (Exception e) {
    42. e.printStackTrace();
    43. }
    44. return results;
    45. }
    46. private void handleResult(ResultSet rs, MappedStatement mappedStatement, List<Object> results) throws Exception {
    47. // 从结果集中一行一行的取数据
    48. // 每一行数据,再一列一列的取数据(包括列的名称和列的值)
    49. // 最终将获取到的每一列的值都映射到目标对象的指定属性中(列的名称和属性名称要一致)
    50. Class<?> resultTypeClass = mappedStatement.getResultTypeClass();
    51. while (rs.next()) {
    52. // 要映射的结果目标对象
    53. Object result = resultTypeClass.newInstance();
    54. // 获取结果集的元数据(目的是取列的信息)
    55. ResultSetMetaData metaData = rs.getMetaData();
    56. int columnCount = metaData.getColumnCount();
    57. for (int i = 0; i < columnCount; i++) {
    58. String columnName = metaData.getColumnName(i + 1);
    59. Field field = resultTypeClass.getDeclaredField(columnName);
    60. field.setAccessible(true);
    61. field.set(result, rs.getObject(columnName));
    62. }
    63. results.add(result);
    64. }
    65. }
    66. private void handleParameter(PreparedStatement statement, BoundSql boundSql, Object param) throws Exception {
    67. // 判断入参的类型,如果是简单类型,直接处理
    68. if (param instanceof Integer) {
    69. statement.setObject(1, Integer.parseInt(param.toString()));
    70. } else if (param instanceof String) {
    71. statement.setObject(1, param.toString());
    72. } else {
    73. // 获取参数集合信息(#{}处理之后得到的参数信息)
    74. // 如果是POJO类型,则根据参数信息里面的参数名称,去入参对象中获取对应的参数值
    75. List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    76. for (int i = 0; i < parameterMappings.size(); i++) {
    77. Object valueToUser = null;
    78. ParameterMapping parameterMapping = parameterMappings.get(i);
    79. // #{}中的参数名称,也应该和POJO类型中的属性名称一直
    80. String name = parameterMapping.getName();
    81. // 使用反射获取指定name的值
    82. Class<?> clazz = param.getClass();
    83. // 获取指定名称的属性对象
    84. Field field = clazz.getDeclaredField(name);
    85. field.setAccessible(true);
    86. valueToUser = field.get(param);
    87. statement.setObject(i + 1, valueToUser);
    88. }
    89. }
    90. }
    91. private PreparedStatement createStatement(Connection connection, String sql) throws Exception {
    92. PreparedStatement prepareStatement = connection.prepareStatement(sql);
    93. return prepareStatement;
    94. }
    95. private BoundSql getBoundSql(SqlSource sqlSource, Object param) {
    96. BoundSql boundSql = sqlSource.getBoundSql(param);
    97. return boundSql;
    98. }
    99. private Connection getConnection(Configuration configuration) throws Exception {
    100. DataSource dataSource = configuration.getDataSource();
    101. Connection connection = dataSource.getConnection();
    102. return connection;
    103. }
    104. }