源码地址:
https://github.com/mybatis/mybatis-3
文档地址:
https://mybatis.org/mybatis-3/getting-started.html
下载项目,导入项目后
导入mysql依赖
mysql
mysql-connector-java
5.1.35
1.在根目录下创建 mybatis-config.xml,内容为
2.创建jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://****/ccms
username=****
password=****
3.根目录下创建mapper文件夹,在其下面创建test.xml
4.创建相应的实体对象和mapper接口
public class MainTest {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
Demo demo1 = sqlSession.selectOne("org.apache.ibatis.custom.mapper.DemoMapper.selectOne");
System.out.println(demo1);
DemoMapper demoMapper = sqlSession.getMapper(DemoMapper.class);
Demo demo2 = demoMapper.selectOne();
System.out.println(demo2);
}
}
分析这一句代码都做了什么工作
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
1. new SqlSessionFactoryBuilder() 使用的建筑者模式,根据传入的输入流创建了一个XMLConfigBuilder对象,在XMLConfigBuilder中给了configuration、parsed、environment、parser四个变量赋值。然后通过重载的build()方法,返回了一个DefaultSqlSessionFactory。
执行到黄色行时, XMLConfigBuilder中的
configuration 为默认对象;
parsed = false;
environment = null;
parser 为默认对象;
下面看下一句代码,return build(parser.parse());
parser.parse()
此时通过Expressions视图可以看到,parser.evalNode("/configuration")获取到的内容就是resources下jdbc.properties的内容
parseConfiguration()
通过 propertiesElement(root.evalNode(“properties”));方法将jdbc.properties中的内容解析成键值对,并设置到mybatis-config.xml中对应的${}的内容。并设置
XMLConfigBuilder中的 XPathParser parser的variables属性
BaseBuilder中的 Configuration configuration的variables属性
parser.setVariables(defaults);
configuration.setVariables(defaults);
mapperElement(root.evalNode(“mappers”));
root.evalNode(“mappers”)获取的是mybatis-config.xml中的mapper标签的内容,格式如下:
environmentsElement(root.evalNode(“environments”));
通过该方法反射实例化dataSource
mapperElement(root.evalNode(“mappers”));
通过该方法循环解析mapper文件,将cachae-ref、cache、parameterMap、resultMap、sql、操作数据库方式(select、inser、update、delete)等分别存储
此时,执行结束后,成功返回SqlSessionFactory
sqlSession.selectOne(“org.apache.ibatis.custom.mapper.DemoMapper.selectOne”);
到此,demo1的结果就已经查询出来了。
sqlSession.getMapper(DemoMapper.class)
笔者看到这里已经有点懵圈了,DemoMapper是在什么时候加载的,为什么sqlSession可以获取到DemoMapper对象。
带着这种疑惑,从头再跟踪一下SqlSessionFactory 的创建过程。
就是在实例化SqlSessionFactory 时调用的parse()中,调用的bingMapperForNamespace(),如下图(黄色行)
然后调用下图方法
下图可见,加入的map对象为clase对象和mapper代理对象的键值对。
到这里,一切豁然开朗,sqlSession对象保存了所有mapper的代理对象,通过mapper加方法名作为key,在sqlSession对象的configuration属性中的mappedStatements集合中,获取对应的MappedStatement ,然后通过 Executor对象执行。