MyBatis源码分析(一)
MyBatis故事:
官方文档:http://www.mybatis.org/mybatis-3/
GitHub:https://github.com/mybatis
通过在MyBatis的官方网站,我们会看到和MyBatis相关的一些软件产品:
MyBatis Migrations 是一款数据库迁移工具 http://www.mybatis.org/migrations;
MyBatipse (Eclipse plugin) ,Eclipse插件提供在编写xml配置文件时的内容提示和验证;
MyBatis Generator 代码生成工具;
What is MyBatis?
MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis SQL mapper framework for Java可以将其称之为Java持久层框架.
MyBatis 的前身是apache下的一个开源项目iBatis, iBATIS是一个由Clinton Begin在2002年发起的开源项目,是一个基于Java的持久层框架。
iBATIS:http://ibatis.apache.org
iBATIS这个项目于2010年6月16号由apache迁移到了google code,iBatis3.x并且改名为MyBatis 。
MyBatis: http://code.google.com/p/mybatis/ (现在已经无法打开)
2013年11月MyBatis又从google code将代码迁移到Github。
MyBatis和Hibernate
MyBatis的作者:Clinton Begin 加拿大人 https://www.linkedin.com/in/clintonbegin
Hibernate 2001年推出的Java持久层框架,澳大利亚人 Gavin King https://www.linkedin.com/in/GavinKing
人们经常喜欢比较这两款优秀的持久层框架的特点:
| 技术 | 优点 | 缺点 |
| jdbc | 简单,纯粹,一切均可见,最基础的一种技术 |
1:需要手动关闭连接 2:结果集不能自动映射为对象 3:SQL夹杂在代码中,耦合度高,导致硬编码内伤 4:实际开发中SQL经常随需求变动,导致频繁修改,不易维护 |
| jdbcTemplate |
简单、纯粹、自动会话管理、结果集映射 |
需要手动拼装SQL,SQL与Java代码混合在一起,长的SQL管理混乱 |
|
Hibernate JPA |
编程效率高,无需编写SQL。 较完善的二级缓存、自动防SQL注入 |
完全掌握的门槛高; |
| MyBatis |
学习成本低、可以进行更为细腻的SQL优化,减少查询字段、统一的SQL管理 |
需要手动编写维护SQL、表结构变更之后需要手动维护SQL与映射; |
MyBatis的定位
MyBatis专注于SQL本身,其为SQL映射,而非完整的SQL映射,它是一个半自动的ORM框架,需要自己编写SQL语句,这是其优点,也是缺点.
优点:SQL语句单独维护,便于SQL优化,便于发挥SQL的最大性能.
缺点:当数据库表和字段更改后,实体和数据库的映射关系需要手动维护,耗费时间长.
使用场景:是用于性能要求高,有大量的查询操作,适用于互联网项目,如:电商,O2O
互联网项目对持久层的需求:
1:对数据库的访问更加纯粹
2:尽可能不要使用数据库做运算
3:SQL语句尽可能命中索引(字段排序,查询字段,查询条件,尽可能命中索引)
MyBatis实战应用:
Mybatis框架就一个jar包;要使用 MyBatis, 只需将 mybatis-3.5.1.jar 文件置于 classpath 中即可。
使用Maven构建项目
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.</version>
</dependency>
下载MyBatis源码,构建MyBatis项目;https://codeload.github.com/mybatis/mybatis-3/zip/mybatis-3.5.1
如果不出意外,我们解压下载的压缩包,然后通过pom.xml导入IDEA中,通过Maven的compiler就可以正常编译成功,首次编译可能需要一定时间。
为了验证我么编译的项目是否可用,我们可以写一个简单的案例项目去测试一下,也方便后续的断点跟踪源码分析。
创建普通的Maven项目,添加Maven依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency> <!--mysql的jdbc驱动jar包依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.</version>
</dependency> <!--lombok代码生成工具的jar包依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.</version>
</dependency> <!--slf4j日志门面-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.</version>
</dependency> <!--log4j2日志实现-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.11.</version>
</dependency> <!-- cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.</version>
</dependency> <!-- javassist -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.27.-GA</version>
</dependency>
添加resources编译,个人建议添加
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
添加jdbc.properties,根据自身配置
jdbc.username=xxx
jdbc.password=xxxxx
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://xxxx:3306/xxx?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useSSL=false
最后贴上mybatis的xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--dtd的xml约束是有顺序,标签顺序不能错-->
<configuration> <!--mybatis框架的核心功能可以通过该配置进行设置--> <!--配置属性-->
<properties resource="D:\mybatis-3-mybatis-3.5.1\mybatis3-test\src\main\resources\jdbc.properties"/> <settings>
<!--mybatis输出日志,采用何种组件输出-->
<setting name="logImpl" value="SLF4J"/>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings> <!--类型别名-->
<typeAliases>
<typeAlias type="com.xxx.model.User" alias="User"/>
</typeAliases> <typeHandlers>
<!--自定义的类型转换器-->
<typeHandler handler="com.xxx.type.CryptHandlerType"
javaType="com.xxx.model.IdCardType"/>
</typeHandlers> <!--插件-->
<!--
<plugins>
<plugin interceptor="com.xxx.plugin.xxxx"></plugin>
</plugins>
--> <!--多环境配置,默认开发-->
<environments default="development">
<environment id="development">
<transactionManager type="org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment> <environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment> <environment id="product">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments> <!--映射器-->
<mappers> <mapper resource="com/bjpowernode/mapper/UsersMapper.xml"/>
</mappers> </configuration>
日志配置
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug"> <Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders> <Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
贴上本人的项目结构,仅供参考

MyBatis独立使用
//通过配置文件获取输入流
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml"); //构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); //打开session
SqlSession sqlSession = sqlSessionFactory.openSession(); //第四步 获取Mapper接口对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class); //第五步 调用Mapper接口对象的方法操作数据库
User user = mapper.selectByPrimaryKey(); //获取结果,处理业务
log.info("查询结果:",user.getId());
当我们数据库配置等都设置完毕,正常来说查询数据是不会出现异常的,这样就说明我们的源码编译是成功的。
MyBatis Generator (MBG)
MyBatis Generator 简称MBG,是用Java语言开发的一个代码生成工具,可以深入分析你的数据库和表,帮助你生成基本的对数据库的CRUD操作代码以及QBC风格的条件查询,但是表连接、存储过程等这些复杂SQL的定义需要我们手工编写。
MyBatis Generator 生成3个东西:
1、POJO
2、Mapper XML Files
3、Mapper interface
MyBatis Generator 生成代码不需要依赖任何第三方jar包,仅仅需要一个jdbc驱动包;
文档:http://www.mybatis.org/generator/
Github:https://github.com/mybatis/generator
原来MyBatis Generator老版本:ibator,用于iBatis代码生成;
1、配置MyBatis Generator (MBG) 的配置文件;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!--在配置文件中使用占位符引用该属性文件的值-->
<properties resource="jdbc.properties"/> <!-- 指定连接数据库的JDBC驱动包所在位置,指定到你本机的完整路径 -->
<classPathEntry location="F:/mysql-connector-java-5.1.46.jar"/> <!-- 配置table表信息内容体,targetRuntime指定采用MyBatis3的版本 -->
<context id="tables" targetRuntime="MyBatis3"> <!-- 抑制生成注释,由于生成的注释都是英文的,可以不让它生成 -->
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator> <!-- 配置数据库连接信息 -->
<connectionFactory>
<property name="driverClass" value="${jdbc.driver}"/>
<property name="connectionURL" value="${jdbc.url}"/>
<property name="userId" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</connectionFactory> <!-- 配置数据库连接信息 connectionFactory与jdbcConnection只能配置其一-->
<!--
<jdbcConnection driverClass="COM.ibm.db2.jdbc.app.DB2Driver"
connectionURL="jdbc:db2:TEST"
userId="db2admin"
password="db2admin">
</jdbcConnection>
--> <!-- 生成model类,targetPackage指定model类的包名, targetProject指定生成的model放在eclipse的哪个工程下面-->
<javaModelGenerator targetPackage="org.mybatis.model" targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
<property name="trimStrings" value="false" />
</javaModelGenerator> <!-- 生成MyBatis的Mapper.xml文件,targetPackage指定mapper.xml文件的包名, targetProject指定生成的mapper.xml放在eclipse的哪个工程下面 -->
<sqlMapGenerator targetPackage="org.mybatis.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
</sqlMapGenerator> <!-- 生成MyBatis的Mapper接口类文件,targetPackage指定Mapper接口类的包名, targetProject指定生成的Mapper接口放在eclipse的哪个工程下面 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="org.mybatis.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false" />
</javaClientGenerator> <!-- 数据库表名及对应的Java模型类名 -->
<table tableName="user"
domainObjectName="User"
enableCountByExample="false"
enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
selectByExampleQueryId="false"/>
</context> </generatorConfiguration>
1、生成代码
--通过命令行生成 java -jar mybatis-generator-core-1.3.7.jar -configfile generatorConfig.xml (用得比较少)
--通过Ant生成 (ant几乎被淘汰了)
--通过java程序生成
--通过maven生成
<plugins>
<!--mybatis代码自动生成插件-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.</version>
<configuration>
<!--配置文件的位置-->
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
<!--生成代码过程中是否打印日志-->
<verbose>true</verbose>
<!--生成时是否覆盖java文件,xml文件总是合并-->
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
--通过Eclipse生成
建议不要用mysql驱动8.0, 用5.1.x系列的驱动;
使用maven插件通过以下方式即可自动生成。

在源码分析的前面,我会分享一些MyBatis的常规应用
MyBatis源码分析(一)的更多相关文章
- MyBatis源码分析-MyBatis初始化流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析(5)——内置DataSource实现
@(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...
- MyBatis源码分析(4)—— Cache构建以及应用
@(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...
- MyBatis源码分析(3)—— Cache接口以及实现
@(MyBatis)[Cache] MyBatis源码分析--Cache接口以及实现 Cache接口 MyBatis中的Cache以SPI实现,给需要集成其它Cache或者自定义Cache提供了接口. ...
- MyBatis源码分析(2)—— Plugin原理
@(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...
- 【MyBatis源码分析】select源码分析及小结
示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...
- MyBatis源码分析之环境准备篇
前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...
- Mybatis源码分析-BaseExecutor
根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...
- Mybatis源码分析-StatementHandler
承接前文Mybatis源码分析-BaseExecutor,本文则对通过StatementHandler接口完成数据库的CRUD操作作简单的分析 StatementHandler#接口列表 //获取St ...
随机推荐
- xmake v2.3.4 发布, 更加完善的工具链支持
为了让xmake更好得支持交叉编译,这个版本我重构了整个工具链,使得工具链的切换更加的方便快捷,并且现在用户可以很方便地在xmake.lua中扩展自己的工具链. 关于平台的支持上,我们新增了对*BSD ...
- Go语言json编码驼峰转下划线、下划线转驼峰
目录 一.需求 二.实现 三.使用 JsonSnakeCase统一转下划线json JsonSnakeCase统一转驼峰json 一.需求 golang默认的结构体json转码出来,都是大写驼峰的,并 ...
- 小菜成长之路,警惕沦为 API 调用侠
小菜(化名)在某互联网公司担任运维工程师,负责公司后台业务的运维保障工作.由于自己编程经验不多,平时有不少工作需要开发协助. 听说 Python 很火,能快速开发一些运维脚本,小菜也加入 Python ...
- 有关指针 -> 和* 的重载
1, #include<iostream> #include<string> using namespace std; class test{ int i; public: t ...
- springboot使用自定义异常
sprinboot使用自定义注解 创建自定义异常类,继承RuntimeException public class MyException extends RuntimeException { p ...
- UI 自动化遇到的坑
1,ElementNotInteractableException: Message: element not interactable 该解决方法是用xpath定位,然后使用js操作元素,点击之类 ...
- CSS小功能实现
1.css实现三角形效果 #prev { display: block; width:; height:; border-bottom: 7px solid #4d4d4f; border-right ...
- 通信中的错误代码 (repost from https://blog.csdn.net/zzhuan_1/article/details/80066716)
• 100 - 继续.• 101 - 切换协议.• 110 重新启动标记答复.• 120 服务已就绪,在 nnn 分钟后开始.• 125 数据连接已打开,正在开始传输.• 150 文件状态正常,准备打 ...
- PN532模块连接-读卡失败原因
第一步:点击发现NFC设备 第二步:点击读整卡:读取卡片内容. 若不成功,把UID卡移开,再放一次.再点第一步,显示发现NFC,再点第二步.反复操作,直到读取到为止.2-3次一般都会成功 . 相关软件 ...
- 重识Java8函数式编程
前言 最近真的是太忙忙忙忙忙了,很久没有更新文章了.最近工作中看到了几段关于函数式编程的代码,但是有点费解,于是就准备总结一下函数式编程.很多东西很简单,但是如果不总结,可能会被它的各种变体所困扰.接 ...