Maven中的Mybatis:熟悉mybatis的使用

MyBatis学习

  • mybatis基本使用步骤
    • 1、创建Maven项目并在pom.xml文件中配置依赖与插件等信息
    • 2、编写dao接口、表的实体类、daoImpl、mapper
    • 3、编写mybatis主配置文件,实现数据库连接,指定mapper文件
    • 4、封装创建SqlSession对象方法
    • 5、传统 Dao开发方式,通过操作mybatis主配置文件,在DaoImpl中执行sql语句
      • 解析步骤
      • 总结:传统 Dao开发方式的分析
  • mybatis使用进阶
    • 减少接口实现类(daoImpl):jdk动态代理
  • mybatis的sql执行流程
    • getMapper方法执行流程
    • Mapper接口及其映射文件加载到knownMappers中的流程
  • sql执行流程分析
    • 寻找sql
    • 执行sql

通过这篇文章,你可以了解:
1、mybatis传统dao开发方式
2、mybatis的dao代理开发方式
3、mybatis的sql执行流程

mybatis基本使用步骤

1、创建Maven项目并在pom.xml文件中配置依赖与插件等信息

  1. 配置日志文件(settings传送门)

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    settings>
  1. 首先需要加入mybatis与mysql-connector-java的依赖(依赖代码在官方文档都有说明)
<dependency>
      <groupId>org.mybatis< /groupId>
      <artifactId>mybatis< /artifactId>
      <version>3.5.1< /version>
    dependency>
    
    <dependency>
      <groupId>mysql< /groupId>
      <artifactId>mysql-connector-java< /artifactId>
      <version>8.0.25< /version>
    dependency>
  dependencies>
  1. 配置文件过滤插件
<build>
	<resources>
      <resource>
        <directory>src/main/javadirectory>
        <includes>
          
          <include>**/ *.xml< /include>
          <include>**/ *.properties< /include>
        includes>
        <filtering>falsefiltering>
      resource>
      <resource>
        <directory>src/main/resources< /directory>
        <includes>
          <include>\*\*/\*.xml< /include>
          <include>\*\*/\*.properties< /include>
        includes>
        <filtering>false< /filtering>
      resource>
    resources>
 build>

2、编写dao接口、表的实体类、daoImpl、mapper

3、编写mybatis主配置文件,实现数据库连接,指定mapper文件


<mapper namespace="com.lanan.dao.CityDao">
    <select id="findCity" resultType="com.lanan.domain.City">
        select id,name,provinceid from city
    select>
mapper>

4、封装创建SqlSession对象方法

public class MyBatisUtil { 
    //定义 SqlSessionFactory 
    private static SqlSessionFactory factory = null; 
    static { 
        //使用 静态块 创建一次 SqlSessionFactory 
        try{ 
            String config = "mybatis-config.xml"; 
            //读取配置文件 
            InputStream in = Resources.getResourceAsStream(config); 
            //创建 SqlSessionFactory 对象 
            factory = new SqlSessionFactoryBuilder().build(in); 
        }catch (Exception e){ 
            factory = null; 
            e.printStackTrace(); 
        } 
    } 
    /* 获取 SqlSession 对象 */ 
    public static SqlSession getSqlSession(){ 
        SqlSession session = null; 
        if( factory != null){ 
            session = factory.openSession(); 
        } 
        return session; 
    } 
}

5、传统 Dao开发方式,通过操作mybatis主配置文件,在DaoImpl中执行sql语句

/**
* 最基本的使用方式,
*/
//1、获取SqlSession对象
SqlSession session =MyBatisUtil.getSqlSession();
//2、指定要执行sql的mapper文件的nameSpace+.+id
String sqlId ="com.lanan.dao.CityDao" + "." + "findCity";
//3、通过sqlId找到执行语句
List<City> list = session.selectList(sqlId);
//关闭资源
session.close();
return list;

解析步骤

主要解析第六步,在第六步可以看出有创建了大量对象,但其中最重要的是SqlSession对象的创建通过sqlId找到执行语句

  • Resources:负责读取配置文件的对象
  • SqlSessionFactory:SqlSessionFactory是接口,实现类DefaultSqlSessionFactory(spring与mybatis集成中就是创建了这个实现类对象), SqlSessionFactory对象创建会消耗大量资源,一个项目中有一个即可,这里可以通过封装(static SqlSessionFactory)
  • SqlSession:类似于javaweb项目中编写得DbUtil包封装对数据库的操作,是接口,实现类:DefaultSqlSession
  • sqlId:通过这个告诉mybatis怎么去找执行的sql语句
  • 为解决openSession的线程安全问题:openSession()使用在sql语句之前,在sql语句之后关闭close

总结:传统 Dao开发方式的分析

Dao的实现类其实并没有干什么实质性的工作,真正对 DB进
行操作的工作其实是由框架通过 mapper中的 SQL完成的。
MyBatis 框架就抛开了 Dao 的实现类,直接定位到映射文件 mapper 中的相应 SQL 语句,对DB进行操作。这种对 Dao的实现方式称为 Mapper的动态代理方式

mybatis使用进阶

使用动态代理绕过接口实现类的编写

减少接口实现类(daoImpl):jdk动态代理

		//访问mybatis读取city数据
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        //动态获取dao接口实现类
        CityDao dao = sqlSession.getMapper(CityDao.class);
        //数据插入
        List<City> list = dao.findAngleCity(12, "呼伦贝尔");
        sqlSession.close();
        //处理数据
        list.forEach(System.out::println);

从上面代码可以看出通过传入接口的class对象,mybatis便用getMapper方法,通过jdk的动态代理创建了impl类,减少了实现类的创建。

mybatis的sql执行流程

getMapper方法执行流程

使用该方法会创建一个MapperProxy对象,该对象就是jdk动态代理的产物

  • 项目启动的时将Mapper加载并解析存储到Configuration对象
  • 这个方法会先去Configuration对象中获取Mapper对象(this.configuration.getMapper(type, this))
  • 通过Configuration对象中的MapperRegistry对象属性,继续调用getMapper方法(this.configuration.mapperRegistry.getMapper(type, sqlSession))
  • knownMappers是一个HashMap为底层的map对象
  • 根据type类型,从MapperRegistry对象中的knownMappers获取到当前类型对应的代理工厂类,然后通过代理工厂类生成对应Mapper的代理类((MapperProxyFactory)this.configuration.mapperRegistry.knownMappers.get(type).newInstance(sqlSession))

可以看出最后是使用代理工厂类下newInstance创建了代理对象

Mapper接口及其映射文件加载到knownMappers中的流程

  • 读取mybatis的主配置文件,创建io流
  • 调用SqlSessionFactoryBuilder方法中的build()方法创建SqlSessionFactory对象,过程中会调build(Reader reader, String environment, Properties properties)方法,会创建XMLConfigBuilder对象,并调用其parse方法
  • 然后会继续调用自己的parseConfiguration来解析全部的配置文件
  • 调用自己的mapperElement来解析mappers文件,4种mapper配置方式(两种直接配置的xml映射文件,两种解析直接配置Mapper接口的方式),但不论配置哪种方式,最终MyBatis都会将xml映射文件和Mapper接口进行关联(防止解析失败报错,开发过程中我们应该避免循环依赖的产生)
  • 解析完映射文件之后,调用自身方法bindMapperForNamespace,开始绑定Mapper接口和映射文件
  • 调用Configuration对象的属性MapperRegistry内的addMapper方法,这个方法就是正式将Mapper接口添加到knownMappers,所以上面getMapper可以直接获取

sql执行流程分析

寻找sql

  • dao接口代理对象调用方法,是使用invoke方法
  • 因为代理对象调用的方法不是Object类下的,会继续调用MapperProxy内部类MapperMethodInvoker中的方法cachedInvoker
  • 构造一个MapperMethod对象,这个对象封装了Mapper接口中对应的方法信息以及对应的sql语句信息

执行sql

  • 会根据语句类型以及返回值类型来决定如何执行方法(selectList)
  • 方法会委派给了Execute去执行query方法,最终又会去调用queryFromDatabase方法
  • 进入PreparedStatementHandler对象的query方法,可以看到,这一步就是调用了jdbc操作对象PreparedStatement中的execute方法,最后一步就是转换结果集然后返回

你可能感兴趣的:(MyBatis,mybatis,java)