又到了一年一度挪坑日,作为一个码畜,开始了新的复习java之路,除了巩固,更是为了活动下僵硬许久的CRUD操作。那么就从Mybatis这个相对简单的框架开始吧。

Mybatis的使用

由于太久没单独的使用这个框架了,甚至JDBC都有点忘记怎么写了。于是特意再不劳烦spring的前提下,用了下Mybatis查询了下数据库。

过程如下:

  1. 创建个java项目
  2. 引入mybatis的jar包和mysql的驱动jar包
  3. 拷贝过来一个mybatis的配置文件
  4. 写一个接口、一个实体类、一个mapper.xml文件、一个测试类
  5. 准备个Mysql数据库

然后启动,看到查询结果(并没有那么一帆风顺。一会找不到xml一会又找不到驱动的)。下面附上相关的准备事宜。

<dependencies>
        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>

        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.9</version>
        </dependency>
    </dependencies>

配置文件:(要放在resources下面哟,配置文件名字随便)

<?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>
    <environments default="mysql">
        <environment id="mysql">
            <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/mybatislearn?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="xpar"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="EntityDao.xml"/>
    </mappers>
</configuration>

接口、实体类

public class Entity {
    private String name;
    private String value;
    private Integer revision;
    set/get
}
public interface EntityDao {
    Entity getEntity();
}

mapper文件

<?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="per.sjyang.dao.EntityDao">
    <select id="getEntity" resultType="per.sjyang.entity.Entity">
        select * from SJYANG_TEST01
    </select>
</mapper>

测试类:

public class SimpleTest {
    public static void main(String[] args) throws IOException {
        String config = "mybatis.xml";
        //2.读取这个config表示的文件
        InputStream in = Resources.getResourceAsStream(config);
        //3.创建了SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        //5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //6.【重要】指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        String sqlId = "per.sjyang.dao.EntityDao.getEntity";
        //7.【重要】执行sql语句,通过sqlId找到语句
        List<Entity> entityList = sqlSession.selectList(sqlId);
        //8.输出结果
        entityList.forEach( stu -> System.out.println(stu));
        //9.关闭SqlSession对象
        sqlSession.close();
    }
}

别小看上面这些东西,我因为文件放错位置之类的,错了好多次呢。

好了接下来可以使用了之后,开始读一读源码。

Mybatis的架构设计

要读源码我们肯定要先从其架构上来分析,这样有助于我们阅读源码。直接上图:

Mybatis源码学习感悟_mysql

从图上看,Mybatis框架划分为3层结构,其中各层作用如下:

接口层:

Mybatis的接口层对外提供用户对DB的访问,提供这一基础功能的是一个叫做SqlSession的接口类,它是Mybatis的门户,这个接口提供了一些对DB进行操作的基础API。

核心处理层

核心处理层的作用是处理接口层传进来的指令,并将这些指令转换成SQL语句,拼执行相关SQL,然后对结果集进行封装映射。 核心处理层的两个关键类是Configuration和Executor。

基础支持层:

接口层提供API操作,处理层处理API请求,除了这些外,还需要一些基础服务,比如日志记录、事务处理、加载配置文件信息、缓存支持等。比如处理层的将SQL语句、结果集等封装成java对象存储在Configuration,还有Mybatis的一级缓存、二级缓存以及整个架构的运行记录等。

Mybatis框架的作用

其实一个框架的出现都是为了简化大部分重复工作,从而提高工作效率。那么Mybatis的出现其实就是简化我们对数据的操作,让用户不用关注连接和关闭数据库等操作,而是关注实际的业务操作上。

所以说白了就是优化JDBC操作,不知道你是否还记得JDBC操作步骤:

1.加载驱动

2.获取连接

3.创建statement

4.执行查询获取结果

Connection con = null;// 创建一个数据库连接
    PreparedStatement pre = null;// 创建预编译语句对象,一般都是用这个而不用Statement
    ResultSet result = null;// 创建一个结果集对象
    try
    {
        Class.forName("oracle.jdbc.driver.OracleDriver");// 加载Oracle驱动程序
        System.out.println("开始尝试连接数据库!");
        String url = "jdbc:oracle:" + "thin:@127.0.0.1:1521:XE";// 127.0.0.1是本机地址,XE是精简版Oracle的默认数据库名
        String user = "system";// 用户名,系统默认的账户名
        String password = "147";// 你安装时选设置的密码
        con = DriverManager.getConnection(url, user, password);// 获取连接
        System.out.println("连接成功!");
        String sql = "select * from student where name=?";// 预编译语句,“?”代表参数
        pre = con.prepareStatement(sql);// 实例化预编译语句
        pre.setString(1, "刘显安");// 设置参数,前面的1表示参数的索引,而不是表中列名的索引
        result = pre.executeQuery();// 执行查询,注意括号中不需要再加参数
        while (result.next())
            // 当结果集不为空时
            System.out.println("学号:" + result.getInt("id") + "姓名:"
                    + result.getString("name"));
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

所以Mybatis就是优化上述内容,让用户关注sql就好了。具体Mybatis干的事情如图:

Mybatis源码学习感悟_mysql_02

此时看着上面的图和一些相关的配置文件,我们是不是已经能够看到Mybatis大概要做的事情了。那么接下来就探究具体的实现内容吧。

源码阅读前的思考

在源码阅读前,我脑海中的问题有下面几点:

  1. 驱动什么时候加载的,因为讲道理加载一次就可以啦
  2. 连接在什么时机获取的,使用池技术还是每次都获取次连接
  3. 为什么定义个接口就能直接查询sql?我知道用了动态代理,但是这个代理具体实现了什么?
  4. spring具体整合了mybatis的什么内容
  5. mybaits查询有getMapper和直接query查询,实现方式区别?

后续的文章将根据实际阅读到的源码写进来。用来解答上述问题。