一、简介
使用Mybatis有一段时间了,但是一直没有专门去阅读MyBatis框架的源码,Mybatis是一个非常值得我们去阅读的框架,源码里面运用了很多常见的设计模式,如构建者模式、代理模式、模板方法模式等等,都值得我们去学习和借鉴。
下面我们就以搭建一个源码阅读环境开始,一起来看看Mybatis的源码。
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
如果对Mybatis还不熟悉的小伙伴,建议还是先去官网熟悉Mybatis是如何使用的,熟悉以后我们再来看其源码实现。下面我们搭建一个简单的Mybatis 源码Debug环境。
二、源码环境搭建
【a】创建数据库以及表
CREATE DATABASE `user_mybatis`;
USE `user_mybatis`;
/*Table structure for table `user` */
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` varchar(50) DEFAULT NULL COMMENT '用户名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
/*Data for the table `user` */
insert into `user`(`id`,`username`) values (1,'张三'),(2,'李四'),(3,'王五')
【b】创建一个maven项目
目录结构如下图:
pom文件如下所示:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
【c】mybatis配置文件mybatis-config.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">
<configuration>
<!--一些重要的全局配置-->
<settings>
<!--<setting name="cacheEnabled" value="true"/>-->
<!--<setting name="lazyLoadingEnabled" value="true"/>-->
<!--<setting name="multipleResultSetsEnabled" value="true"/>-->
<!--<setting name="useColumnLabel" value="true"/>-->
<!--<setting name="useGeneratedKeys" value="false"/>-->
<!--<setting name="autoMappingBehavior" value="PARTIAL"/>-->
<!--<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>-->
<!--<setting name="defaultExecutorType" value="SIMPLE"/>-->
<!--<setting name="defaultStatementTimeout" value="25"/>-->
<!--<setting name="defaultFetchSize" value="100"/>-->
<!--<setting name="safeRowBoundsEnabled" value="false"/>-->
<!--<setting name="mapUnderscoreToCamelCase" value="false"/>-->
<!--<setting name="localCacheScope" value="STATEMENT"/>-->
<!--<setting name="jdbcTypeForNull" value="OTHER"/>-->
<!--<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>-->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/user_mybatis?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
【d】创建实体类对象
public class User {
private String id;
private String username;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
'}';
}
}
【e】声明mapper接口以及mapper.xml
public interface UserMapper {
/**
* 查询用户信息
*/
User getById(@Param("id") Long id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wsh.mybatis.mybatisdemo.mapper.UserMapper">
<select id="getById" resultType="com.wsh.mybatis.mybatisdemo.entity.User">
select * from user where id = #{id}
</select>
</mapper>
【f】测试类
class MybatisDemoApplicationTests {
public static void main(String[] args) {
//1、读取配置文件
String resource = "mybatis-config.xml";
InputStream inputStream;
SqlSession sqlSession = null;
try {
inputStream = Resources.getResourceAsStream(resource);
//2、初始化mybatis,创建SqlSessionFactory类实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//3、创建Session实例
sqlSession = sqlSessionFactory.openSession();
//4、获取Mapper接口
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//5、执行SQL操作
User user = userMapper.getById(1L);
System.out.println(user);
} catch (IOException e) {
e.printStackTrace();
} finally {
//6、关闭sqlSession会话
if (null != sqlSession) {
sqlSession.close();
}
}
}
}
运行程序,如下图,可以看到成功查询到记录,说明Mybatis环境搭建成功。
通过上面的示例,我们总结一下Mybatis使用的大体流程,如下图所示:
可以看到,主要分为了如上图的几个步骤,这几个步骤也是Mybatis的核心了,所以我们阅读源码也是从这几个部分切入,逐步逐步去了解里面的实现细节,接下来就分好几篇文章总结一下Mybatis常见组件的实现原理。