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 ...
随机推荐
- 哪些年,我们玩过的Git
作者:玩世不恭的Coder公众号:玩世不恭的Coder时间:2020-06-05说明:本文为原创文章,未经允许不可转载,转载前请联系作者 哪些年,我们玩过的Git 前言一.前期工作常用基本概念的理解G ...
- zabbix服务无法正常启动
环境介绍 操作系统 centos 7.4 zabbix 3.4.7 故障现象说明 zabbix agent无法启动 web 监控不到客户端服务器 查看日志报错 提示不能打开日志,不能创建信 ...
- k8s学习-资源控制器
4.3.资源控制器 4.3.1.概念 Kubernetes中内建了很多种controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为. 4.3.2.分类 Replication ...
- 大话计算机网络一 聊聊UDP
引言 UDP是一个简单的面向数据报的运输层协议 UDP不提供可靠性,它把应用程序传给IP层得数据发送出去,不保证它们能达到目的地 UDP首部 端口号表示发送进程和接受进程. UDP长度字段指的是UDP ...
- [转] VMware中的Ubuntu无法通过桥接方式上网
遇到的问题:主机可以上网(使用了代理),VMware设置为桥接方式连网.在主机中可以ping通虚拟机,在虚拟机中也可以ping通主机,可是在虚拟机中始终连接不了因特网. 感谢刘洋同学的博文,“在桥接模 ...
- Springboot打包放到Tomcat中报错 One or more listener fail to start
1.问题: Springboot项目直接启动不报错,打war包放到外部容器Tomcat.东方通上,在@Weblistener注解的监听器类中报错 One or more listener fail t ...
- Python学习之路——pycharm的第一个项目
Python学习之路——pycharm的第一个项目 简介: 上文中已经介绍如何安装Pycharm已经环境变量的配置.现在软件已经安装成功,现在就开始动手做第一个Python项目.第一个“Hello W ...
- rust 编码模式
➜ hello_cargo git:(master) ✗ rustc --print code-models Available code models: small kernel medium la ...
- ca78a_c++_字符串流在内存中的输入输出(速度快)
/*ca78a_c++_字符串流在内存中的输入输出**字符串流:在内存中的输入输出.(在内存中进行,速度快)**文件流 :是对文件进行输入和输出.(在磁盘里面进行)istringstream(输入), ...
- 08.DRF-反序列化
三.反序列化使用 3.1 验证 使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象. 在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功 ...