目录:
1、开发重点知识
- MyBatis快速入门
- result 与 resultMap
- 怎么样传递多个参数
- 获取主键
- SQL 的参数
- 代码生成器
- 关联查询
- 缓存
- 与 spring 的集成
2、源码骨架分析
- 整体架构
- 日志模块分析
- 数据源模块分析
- 缓存模块分析
- 反射模块分析
3、源码流程分析
- 流程整体分析
- 配置加载阶段
- 代理阶段分析
- 数据读写阶段
4、知识拾遗
- 与 spring 的结合源码分析
- 插件开发
- 手写 MyBatis
MyBatis - 1、开发重点知识
1、MyBatis快速入门
1.1 为什么需要ORM框架?
传统JDBC编程存在的弊端:
- 工作量大,操作数据库至少需要5步
- 业务代码和计数代码耦合
- 连接资源手动关闭,带来隐患
1.2 MyBatis 是什么?
Mybatis 前身是 iBatis,其源于“Internet” 和 “ibatis” 的组合,本质使用中半自动的ORM框架,除了POJO和映射关系之外,还需要编写SQL语句;
mybatis 快速入门:
2、resultType 与 resultMap
2.1 resultType 元素
当使用resultType做SQL语句返回结果类型处理时,对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应,而resultType中的内容就是pojo在本项目中的位置。
自动映射注意事项
- 前提:SQL 列名 和 JavaBean 的属性是一致的;
- 使用resultType,如用简写需要配置 typeAliases (别名);
- 如果 列名 和 JavaBean 不一致,但列名符合单词下划线分割,Java 是驼峰命名法,则 mapUnderscoreToCamelCase 可设置为 true;(设置自动驼峰转换)
2.2 resultMap 元素
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来,在对复杂语句进行联合映射的时候,它很可能可以代替数千行的同等功能的代码。
ResultMap 的设计思想是,简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了
resultMap 可以继承
使用场景:
- 字段有自定义转换规则
- 复杂的多表查询
2.2.1 resultMap元素 子元素
- id –一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能,一对多的查询中用于结果集合并;
- result – 注入到字段或 JavaBean 属性的普通结果
- association – 一个复杂类型的关联;许多结果将包装成这种类型
- 嵌套结果映射 – 关联可以指定为一个 resultMap 元素,或者引用一个
- collection – 一个复杂类型的集合
- 嵌套结果映射 – 集合可以指定为一个 resultMap 元素,或者引用一个
3、怎么样传递多个参数
- 使用map传递参数;可读性差,导致可维护性和可扩展性差,杜绝使用;
- 使用注解传递参数;直观明了,当参数较少一般小于5个的时候,建议使用;
- 使用Java Bean的方式传递参数;当参数大于5个的时候,建议使用;
4、获取主键
4.1 insert标签相关属性
SQL 示例:用于主键为自增字段时
4.2 selectKey元素
mysql 的写法示例:
5、SQL 元素 和 参数
SQL 元素:
- 用来定义可重用的 SQL 代码段,可以包含在其他语句中;
参数:
向sql语句中传递的可变参数
- 预编译 #{}:将传入的数据都当成一个字符串,会对自动传入的数据加一个单引号,能够很大程度防止sql注入;
- 传值 ${}:传入的数据直接显示生成在sql中,无法防止sql注入;
- 表名、选取的列是动态的,order by和in操作, 可以考虑使用$
SQL 注入示例:or 1=1
动态 SQL 元素
where 标签 是 trim 标签的一种简写操作
批量操作
通过 foreach 动态拼装 SQL 语句
使用 batch 类型的执行器(executor )
@Test
// 批量更新
public void testBatchExcutor() {
// 2.获取sqlSession,并指定为批量处理类型
// SqlSession sqlSession = sqlSessionFactory.openSession(true);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, true);
// 3.获取对应mapper
TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
TUser user = new TUser();
user.setUserName("mark");
user.setRealName("毛毛");
TPosition positon1 = new TPosition();
positon1.setId(1);
user.setPosition(positon1);
System.out.println(mapper.insertSelective(user));
TUser user1 = new TUser();
user1.setId(3);
user1.setUserName("cindy");
user1.setRealName("王美丽");
user.setPosition(positon1);
System.out.println(mapper.updateIfAndSetOper(user1));
// 需要手动提交,commit时才是正在的执行 SQL 语句
sqlSession.commit();
System.out.println("----------------");
System.out.println(user.getId());
System.out.println(user1.getId());
}
6、代码生成器 Mybatis Generator (MBG)
MyBatis Generator:MyBatis 的开发团队提供了一个很强大的代码生成器,代码包含了数据库表对应的实体类 、Mapper 接口类、 Mapper XML 文件等,这些代码文件中几乎包含了全部的单表操作方法。
使用 MBG 可以极大程度上方便我们使用 MyBatis,还可以减少很多重复操作;
XML 节点如下:
运行 MBG
-
从命令提示符:使用 XML 配置文件
- java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml
- 使用场景:对逆向工程定制较少,项目工程结构比较复杂的情况
-
作为 maven plugin
- mvn mybatis-generator:generate
- 使用场景:对逆向工程定制较多,项目工程结构比较单一的情况
pom 文件中添加插件
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</build>
添加配置文件:
jdbc_driver=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
jdbc_username=root
jdbc_password=lixun033
project_src =src/main/java
project_mapper_xml =src/main/resources/sqlmapper
#class_path=C:/Users/admin/.m2/repository/mysql/mysql-connector-java/5.1.18/mysql-connector-java-5.1.18.jar
class_path=D:/devTools/LocalRepository/mysql/mysql-connector-java/5.1.18/mysql-connector-java-5.1.18.jar
<?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="db.properties" />
<classPathEntry location="${class_path}" />
<context id="context1" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="${jdbc_driver}"
connectionURL="${jdbc_url}" userId="${jdbc_username}" password="${jdbc_password}" />
<javaModelGenerator targetPackage="com.enjoylearning.mybatis.entity"
targetProject="${project_src}" />
<sqlMapGenerator targetPackage="." targetProject="${project_mapper_xml}" />
<javaClientGenerator targetPackage="com.enjoylearning.mybatis.mapper"
targetProject="${project_src}" type="XMLMAPPER" />
<!-- shema 数据库 tableName表明 -->
<table schema="${jdbc_username}" tableName="t_role"
enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table>
<!-- <table schema="${jdbc_username}" tableName="t_user"
enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table>
<table schema="${jdbc_username}" tableName="t_user_role"
enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table> -->
</context>
</generatorConfiguration>
- 从另一个 java 程序,使用 XML 配置文件
XML 配置文件具体内容如下:
<?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>
<!-- 加载数据库驱动 -->
<classPathEntry location="mysql-connector-java-5.1.18.jar" />
<!-- context:生成一组对象的环境
id:必选,上下文id,用于在生成错误时提示
defaultModelType:指定生成对象的样式
1,conditional:类似hierarchical;
2,flat:所有内容(主键,blob)等全部生成在一个对象中,推荐使用;
3,hierarchical:主键生成一个XXKey对象(key class),Blob等单独生成一个对象,其他简单属性在一个对象中(record class)
targetRuntime:
1,MyBatis3:默认的值,生成基于MyBatis3.x以上版本的内容,包括XXXBySample;
2,MyBatis3Simple:类似MyBatis3,只是不生成XXXBySample;
-->
<context id="context1" targetRuntime="MyBatis3" defaultModelType="flat">
<!-- 生成的Java文件的编码 -->
<property name="javaFileEncoding" value="UTF-8"/>
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="false" />
<!-- 阻止注释中包含时间戳 true:是 : false:否 -->
<property name="suppressDate" value="true" />
<!-- 注释是否包含数据库表的注释信息 true:是 : false:否 -->
<property name="addRemarkComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="lixun033" />
<!-- java模型创建器,是必须要的元素 负责:1,key类(见context的defaultModelType);2,java类;3,查询类
targetPackage:生成的类要放的包,真实的包受enableSubPackages属性控制;
targetProject:目标项目,指定一个存在的目录下,生成的内容会放到指定目录中,如果目录不存在,MBG不会自动建目录
-->
<javaModelGenerator targetPackage="com.enjoylearning.mybatis.entity" targetProject="src/main/java">
<!-- 设置一个根对象,
如果设置了这个根对象,那么生成的keyClass或者recordClass会继承这个类;在Table的rootClass属性中可以覆盖该选项
注意:如果在key class或者record class中有root class相同的属性,MBG就不会重新生成这些属性了,包括:
1,属性名相同,类型相同,有相同的getter/setter方法;
-->
<property name="rootClass" value="com.enjoylearning.mybatis.entity.BaseEntity" />
</javaModelGenerator>
<!-- 生成SQL map的XML文件生成器,
targetPackage:生成的类要放的包,真实的包受enableSubPackages属性控制;
targetProject:目标项目,指定一个存在的目录下,生成的内容会放到指定目录中,如果目录不存在,MBG不会自动建目录
-->
<sqlMapGenerator targetPackage="." targetProject="src/main/resources/sqlmapper">
</sqlMapGenerator>
<!-- 对于mybatis来说,即生成Mapper接口,注意,如果没有配置该元素,那么默认不会生成Mapper接口
type:选择怎么生成mapper接口(在MyBatis3/MyBatis3Simple下):
1,ANNOTATEDMAPPER:会生成使用Mapper接口+Annotation的方式创建(SQL生成在annotation中),不会生成对应的XML;
2,MIXEDMAPPER:使用混合配置,会生成Mapper接口,并适当添加合适的Annotation,但是XML会生成在XML中;
3,XMLMAPPER:会生成Mapper接口,接口完全依赖XML;
注意,如果context是MyBatis3Simple:只支持ANNOTATEDMAPPER和XMLMAPPER
-->
<javaClientGenerator targetPackage="com.enjoylearning.mybatis.mapper" targetProject="src/main/java" type="XMLMAPPER" />
<!-- shema 数据库 tableName表明 -->
<table schema="${jdbc_username}" tableName="t_usre" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
<generatedKey column="id" sqlStatement="MySql"/>
</table>
</context>
</generatorConfiguration>
7、关联查询
阿里规范:
当一定要关联超过 3 张表时,解决方案:
一对一嵌套查询:
嵌套结果:
- 多个表的字段在一起返回
一对多查询:
先查主表:
再查从表:
多对多查询:
分多次查询
8、缓存
8.1 一级缓存:
8.2 二级缓存:
开启二级缓存:
在 XML 文件中,添加 cache 标签即表示开启了 mybatis 的二级缓存。
<cache></cache>
8.3 缓存总结
先查二级缓存再查一级缓存