查询流程:
代码debug分析:
1 public class MyBatisTest { 2 3 public SqlSessionFactory getSqlSessionFactory() throws IOException { 4 String resource = "mybatis-config.xml"; 5 InputStream inputStream = Resources.getResourceAsStream(resource); 6 return new SqlSessionFactoryBuilder().build(inputStream); 7 } 8 9 /** 10 * 1、获取sqlSessionFactory对象: 11 * 解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession; 12 * 注意:【MappedStatement】:代表一个增删改查的详细信息 13 * 14 * 2、获取sqlSession对象 15 * 返回一个DefaultSQlSession对象,包含Executor和Configuration; 16 * 这一步会创建Executor对象; 17 * 18 * 3、获取接口的代理对象(MapperProxy) 19 * getMapper,使用MapperProxyFactory创建一个MapperProxy的代理对象 20 * 代理对象里面包含了,DefaultSqlSession(Executor) 21 * 4、执行增删改查方法 22 * 23 * 总结: 24 * 1、根据配置文件(全局,sql映射)初始化出Configuration对象 25 * 2、创建一个DefaultSqlSession对象, 26 * 他里面包含Configuration以及 27 * Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor) 28 * 3、DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy; 29 * 4、MapperProxy里面有(DefaultSqlSession); 30 * 5、执行增删改查方法: 31 * 1)、调用DefaultSqlSession的增删改查(Executor); 32 * 2)、会创建一个StatementHandler对象。 33 * (同时也会创建出ParameterHandler和ResultSetHandler) 34 * 3)、调用StatementHandler预编译参数以及设置参数值; 35 * 使用ParameterHandler来给sql设置参数 36 * 4)、调用StatementHandler的增删改查方法; 37 * 5)、ResultSetHandler封装结果 38 * 注意: 39 * 四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler); 40 * 41 * @throws IOException 42 */ 43 @Test 44 public void test01() throws IOException { 45 // 1、获取sqlSessionFactory对象 46 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); 47 // 2、获取sqlSession对象 48 SqlSession openSession = sqlSessionFactory.openSession(); 49 try { 50 // 3、获取接口的实现类对象 51 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 52 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); 53 Employee employee = mapper.getEmpById(1); 54 System.out.println(mapper); 55 System.out.println(employee); 56 } finally { 57 openSession.close(); 58 } 59 60 } 61 62 }
Configuration的创建过程如下:
1 /* 2 Configuration的创建过程: 3 1.sqlSessionFactoryBuilder.build(inputStream) 4 5 2.build(InputStream inputStream, String environment, Properties properties); 6 7 3.build(parser.parse())--->parser.parse() 8 9 4.parseConfiguration(parser.evalNode("/configuration")); 10 11 5.private void parseConfiguration(XNode root) { 12 try { 13 Properties settings = settingsAsPropertiess(root.evalNode("settings")); 14 //issue #117 read properties first 15 propertiesElement(root.evalNode("properties")); // ① 读取<properties>,并设置 16 loadCustomVfs(settings); // ② 读取之前<settings>,并设置 17 typeAliasesElement(root.evalNode("typeAliases")); // ③ 读取<typeAliases>,并设置 18 pluginElement(root.evalNode("plugins")); // ④ 读取<plugins>,并设置 19 objectFactoryElement(root.evalNode("objectFactory")); // ⑤ 读取<objectFactory>,并设置 20 objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); // ⑥ 读取<objectWrapperFactory>,并设置 21 reflectorFactoryElement(root.evalNode("reflectorFactory")); // ⑦ 读取<reflectorFactory>,并设置 22 settingsElement(settings); 23 // read it after objectFactory and objectWrapperFactory issue #631 24 environmentsElement(root.evalNode("environments")); // ⑧ 读取<environments>,并设置 25 databaseIdProviderElement(root.evalNode("databaseIdProvider")); // ⑨ 读取<databaseIdProvider>,并设置 26 typeHandlerElement(root.evalNode("typeHandlers")); // ⑨ 读取<databaseIdProvider>,并设置 27 mapperElement(root.evalNode("mappers")); // ⑨ 读取<mappers>,并设置 28 } catch (Exception e) { 29 throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); 30 } 31 } 32 33 // 读取xxxMapper.xml或者xxxMapperAnnotation... 34 6.private void mapperElement(XNode parent) throws Exception { 35 if (parent != null) { 36 for (XNode child : parent.getChildren()) { 37 if ("package".equals(child.getName())) { 38 String mapperPackage = child.getStringAttribute("name"); 39 configuration.addMappers(mapperPackage); 40 } else { 41 String resource = child.getStringAttribute("resource"); 42 String url = child.getStringAttribute("url"); 43 String mapperClass = child.getStringAttribute("class"); 44 if (resource != null && url == null && mapperClass == null) { 45 ErrorContext.instance().resource(resource); 46 InputStream inputStream = Resources.getResourceAsStream(resource); 47 XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); 48 mapperParser.parse(); // 解析mapper,xml--->configurationElement(parser.evalNode("/mapper")); 49 } else if (resource == null && url != null && mapperClass == null) { 50 ErrorContext.instance().resource(url); 51 InputStream inputStream = Resources.getUrlAsStream(url); 52 XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); 53 mapperParser.parse(); 54 } else if (resource == null && url == null && mapperClass != null) { 55 Class<?> mapperInterface = Resources.classForName(mapperClass); 56 configuration.addMapper(mapperInterface); 57 } else { 58 throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one."); 59 } 60 } 61 } 62 } 63 } 64 // 解析具体的mapper.xml 65 7.private void configurationElement(XNode context) { 66 try { 67 String namespace = context.getStringAttribute("namespace"); 68 if (namespace == null || namespace.equals("")) { 69 throw new BuilderException("Mapper's namespace cannot be empty"); 70 } 71 builderAssistant.setCurrentNamespace(namespace); 72 cacheRefElement(context.evalNode("cache-ref")); 73 cacheElement(context.evalNode("cache")); 74 parameterMapElement(context.evalNodes("/mapper/parameterMap")); 75 resultMapElements(context.evalNodes("/mapper/resultMap")); 76 sqlElement(context.evalNodes("/mapper/sql")); 77 buildStatementFromContext(context.evalNodes("select|insert|update|delete")); 78 } catch (Exception e) { 79 throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e); 80 } 81 } 82 */