mybatis原理剖析
mybatis的整体结构、原理、组件等:
mybatis运行总体流程:
//1.Resources工具类,配置文件的加载,将配置文件加载成字节输入流
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//2.解析了配置文件,并创建了sqlSessionFatory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//3.生产sqlSession,默认开启事务,但是不会自动提交,进行更新操作时需手动提交
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.调用sqlSession的方法,进行数据库操作.
List<User> users = sqlSession.selectList("user.findAll");
核心的SimpleExecutor.query的执行sql全过程:
//1:注册驱动,获取连接
Connection connection = configuration.getDataSource().getConnection();
//2:获取sql语句 : select * from user where id = #{u_id} and username = #{u_name};
//转换sql语句:select * from user where id = ? and username = ?; 转换过程对#{}进行解析存储
String sql = mappedStatement.getSql();
BoundSql boundSql = getBoundSql(sql);
//3:获取预处理对象:preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());
//4.设置参数
//获取到了参数的全路径
String paramType = mappedStatement.getParamType();
Class<?> parametertypeClass = getClassType(paramType);
List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();
for (int i = 0; i < parameterMappingList.size(); i++) {
ParameterMapping parameterMapping = parameterMappingList.get(i);
//content为参数名称
String content = parameterMapping.getContent();
//反射获取实体类参数属性值
Field declaredField = parametertypeClass.getDeclaredField(content);
//设置暴力访问
declaredField.setAccessible(true);
Object o = declaredField.get(params[0]);
preparedStatement.setObject(i + 1, o);
}
//5.执行sql
ResultSet resultSet = preparedStatement.executeQuery();
String resultType = mappedStatement.getResultType();
Class<?> resultTypeClass = getClassType(resultType);
ArrayList<Object> objects = new ArrayList<>();
//6.封装返回结果集:取出resultSet结果封装到具体实体类中
while(resultSet.next()){
Object o = resultTypeClass.newInstance();
//元数据
ResultSetMetaData metaData = resultSet.getMetaData();
for (int i = 1;i<=metaData.getColumnCount();i++){
//字段名
String columnName = metaData.getColumnName(i);
//字段的值
Object value = resultSet.getObject(columnName);
//使用反射或者内省,根据数据库表和实体类对应关系,完成封装
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultTypeClass);
Method writeMethod = propertyDescriptor.getWriteMethod();
writeMethod.invoke(o,