MyBatis基本概念
什么是mybatis
2001年,Clinton Begin发起了一个名为iBATIS的开源项目,最初侧重于密码软件的研发,后来发展成为一款基于Java的持久层框架。
2004年,Clinton将iBATIS的名字和源码捐赠给了Apache软件基金会。
2010年,核心开发团队决定离开Apache软件基金会,并且将iBATIS改名为MyBatis。
MyBatis是一款优秀的支持自定义SQL查询、存储过程和高级映射的持久层框架,消除了几乎所有的JDBC代码和参数的手动设置以及结果集的检索。MyBatis可以使用XML或注解进行配置和映射,MyBatis通过将参数映射到配置的SQL形成最终执行的SQL语句,最后将执行SQL的结果映射成Java对象返回。
与其他的ORM(对象关系映射)框架不同,MyBatis并没有将Java对象与数据库表关联起来,而是将Java方法与SQL语句关联。
官方文档: http://www.mybatis.org/mybatis-3/getting-started.html
工作原理
使用MyBatis之前,我们要先理解下MyBatis的工作原理。
工作原理
mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件(也可以用Java文件配置的方式,需要添加@Configuration)中构建出SqlSessionFactory(SqlSessionFactory是线程安全的);
然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,之后关闭SqlSession。
说明:SqlSession是单线程对象,因为它是非线程安全的,是持久化操作的独享对象,类似jdbc中的Connection,底层就封装了jdbc连接。
详细流程如下
-
加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着<select | update | delete | insert>标签项。
-
SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。
-
SqlSession对象完成和数据库的交互:
-
用户程序调用mybatis接口层api(即Mapper接口中的方法)
-
SqlSession通过调用api的Statement ID找到对应的MappedStatement对象
-
通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象
-
JDBC执行sql。
-
借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。
配置文件
mybatis-config.xml
下面根据源码分析下:
程序加载mybatis-config.xml,由SqlSessionFactoryBuilder到SqlSessionFactory的过程。
源码部分解读 SqlSessionFactoryBuilder
- SqlSessionFactoryBuilder加载 XMLConfigBuilder
1.public class SqlSessionFactoryBuilder {
2.
3. //Reader读取mybatis配置文件,传入构造方法
4. //除了Reader外,其实还有对应的inputStream作为参数的构造方法,
5. //这也体现了mybatis配置的灵活性
6. public SqlSessionFactory build(Reader reader) {
7. return build(reader, null, null);
8. }
9.
10. public SqlSessionFactory build(Reader reader, String environment) {
11. return build(reader, environment, null);
12. }
13.
14. //mybatis配置文件 + properties, 此时mybatis配置文件中可以不配置properties,也能使用${}形式
15. public SqlSessionFactory build(Reader reader, Properties properties) {
16. return build(reader, null, properties);
17. }
18.
19. //通过XMLConfigBuilder解析mybatis配置,然后创建SqlSessionFactory对象
20. public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
21. try {
22. XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
23. //下面看看这个方法的源码
24. return build(parser.parse());
25. } catch (Exception e) {
26. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
27. } finally {
28. ErrorContext.instance().reset();
29. try {
30. reader.close();
31. } catch (IOException e) {
32. // Intentionally ignore. Prefer previous error.
33. }
34. }
35. }
36.
37. public SqlSessionFactory build(Configuration config) {
38. return new DefaultSqlSessionFactory(config);
39. }
40.
41.}
XMLConfigBuilder
1./**
2. * mybatis 配置文件解析
3. */
4.public class XMLConfigBuilder extends BaseBuilder {
5. public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
6. this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
7. }
8.
9. private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
10. super(new Configuration());
11. ErrorContext.instance().resource("SQL Mapper Configuration");
12. this.configuration.setVariables(props);
13. this.parsed = false;
14. this.environment = environment;
15. this.parser = parser;
16. }
17.
18. //外部调用此方法对mybatis配置文件进行解析
19. public Configuration parse() {
20. if (parsed) {
21. throw new BuilderException("Each XMLConfigBuilder can only be used once.");
22. }
23. parsed = true;
24. //从根节点configuration
25. parseConfiguration(parser.evalNode("/configuration"));
26. return configuration;
27. }
28.
29. //此方法就是解析configuration节点下的子节点
30. //由此也可看出,我们在configuration下面能配置的节点为以下10个节点
31. private void parseConfiguration(XNode root) {
32. try {
33. propertiesElement(root.evalNode("properties")); //issue #117 read properties first
34. typeAliasesElement(root.evalNode("typeAliases"));
35. pluginElement(root.evalNode("plugins"));
36. objectFactoryElement(root.evalNode("objectFactory"));
37. objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
38. settingsElement(root.evalNode("settings"));
39. environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631
40. databaseIdProviderElement(root.evalNode("databaseIdProvider"));
41. typeHandlerElement(root.evalNode("typeHandlers"));
42. mapperElement(root.evalNode("mappers"));
43. } catch (Exception e) {
44. throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
45. }
46. }
}
通过以上源码,我们就能看出,在mybatis的配置文件中:
- configuration节点为根节点。
- 在configuration节点之下,我们可以配置10个子节点, 分别为:
- properties
- typeAliases
- plugins
- objectFactory
- objectWrapperFactory
- settings
- environments
- databaseIdProvider
- typeHandlers
- Mappers