一、简介
使用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
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; | |
} | |
public String toString() { | |
return "User{" + | |
"id='" + id + '\'' + | |
", username='" + username + '\'' + | |
'}'; | |
} | |
} |
【e】声明mapper接口以及mapper.xml
public interface UserMapper { | |
/** | |
* 查询用户信息 | |
*/ | |
User getById(@Param("id") Long id); | |
} | |
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常见组件的实现原理。