概述
定义
MyBatis官网** mybatis – MyBatis 3 | Introduction 最新版本为3.5.9**
MyBatis是一个的ORM框架,支持自定义SQL、存储过程和高级映射。MyBatis对JDBC做了稳定封装使我们不再需要直接操作繁琐JDBC的代码进行参数的手动设置和结果检索。在MyBatis可以使用XML、注解和Java pojo映射到数据库记录。
由于我们Java技术栈程序员对MyBatis都已非常熟悉,本篇我们则主要是从源码的角度去收获不一样MyBatis理解之旅。众所周知JDBC操作核心步骤包括创建连接、创建Statement和执行SQL语句、ResultSet接收结果;MyBatis的ORM核心思想是用于实现面向对象编程语言里不同类型系统的数据之间的转换,我们接下来探索三个问题。
- 如何获取数据库源?
- 如何执行Sql语句?
- 结果集如何处理?
源码探索
JDBC
我们先简单回顾下JDBC操作MySQL数据库的例子
package org.apache.ibatis.itxs;
import java.sql.*;
public class JDBCMain {
public static void main(String[] args) {
Connection connection = null;
Statement st = null;
ResultSet rs = null;
try {
//第一种注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//第二种方式也可加载驱动程序
//Class.forName("com.mysql.jdbc.Driver");
//2.建立连接,参数一:协议+访问数据库,参数二:用户名,参数三:密码
connection = DriverManager.getConnection("192.168.50.68:3306/testdb?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull", "test", "");
//3.创建statement,跟数据库打交道一定需要这个对象
st = connection.createStatement();
//4.执行查询
String sql = "select * from blog";
rs = st.executeQuery(sql);
//5.遍历查询每一条记录
while(rs.next()) {
int id = rs.getInt("id");
String title = rs.getString("title");
String content = rs.getString("content");
System.out.println("id = " + id + "; title = " + title + "; content = " + content);
}
connection.close();
st.close();
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
搭建源码调试环境
mybatis源码GitHub - mybatis/mybatis-3: MyBatis SQL mapper framework for Java
由于我们直接在mybatis源码演示demo,所以需要先将mybatis源码下的pom中mysql-connector-java依赖的**<scope>
test </scope>
**注释掉,
数据库准备Blog表并初始数据,新建resources并标记为资源目录,常见mybatis-config.xml和db.properties文件,创建实体类Blog、还有对应Mapper接口、Mapper xml文件。创建一个main类调试。
Blog表语句
CREATE TABLE `blog` (
`id` BIGINT NOT NULL,
`title` VARCHAR(100) DEFAULT NULL,
`content` VARCHAR(300) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
insert into blog(id,title,content) values(1,'Java','面向对象');
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>
<properties resource="config/db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/apache/ibatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
**db.properties **
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://192.168.50.68:3306/testdb?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
username=test
password=
Blog.java
package org.apache.ibatis.example;
public class Blog {
private long id;
private String title;
private String content;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Blog{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
BlogMapper.java
package org.apache.ibatis.example;
public interface BlogMapper {
Blog selectBlog111(Long id);
}
BlogMapper.xml
<?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="org.apache.ibatis.example.BlogMapper">
<select id="selectBlog" resultType="org.apache.ibatis.example.Blog">
select * from Blog where id = #{id}
</select>
</mapper>
Main.java
package org.apache.ibatis.itxs;
import org.apache.ibatis.example.Blog;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) {
String resource = "config/mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()) {
Blog blog = session.selectOne("org.apache.ibatis.example.BlogMapper.selectBlog", 1);
System.out.printf(blog.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
如何获取数据源
加载数据源配置信息
我们这里采用基于XML配置文件方式来演示,这样方式来学习通过mybatis源码笔者也认为最能得到,是Main类的main方法逐步调试进入mybatis的源码,从下面的堆栈调用链可以看出操作mybatis是从SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream)这一行开始,在这里先读取mybatis配置文件数据加载到全局配置Configuration里
首先parseConfiguration(XNode root)这个方法主要是初始化处理mybatis配置文件,我们发现配置文件中的**<properties resource="config/db.properties">
****</properties>
**在源码中是放在最前面,这个也解释如果我们把这行放在environments节点后面XML格式校验提示错误。org.apache.ibatis.builder.xml.XMLConfigBuilder中parseConfiguration方法代码如下:
private void parseConfiguration(XNode roo